+/* $OpenLDAP$ */
/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, Redwood City, California, USA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License. A copy of this license is available 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
-
+/* pull in lber */
+#include <lber.h>
-#ifdef WINSOCK
-#include "msdos.h"
-#include <winsock.h>
-#endif
+/* include version and API feature defines */
+#include <ldap_features.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 2004
+#define LDAP_VENDOR_NAME "OpenLDAP"
+
+/* OpenLDAP API Features */
+#define LDAP_API_FEATURE_X_OPENLDAP LDAP_VENDOR_VERSION
+
+#if defined( LDAP_API_FEATURE_X_OPENLDAP_REENTRANT ) || \
+ ( 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 /* ldap:/// default LDAP port */
+#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
-/* 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 */
-
-/*
+#define LDAP_ROOT_DSE ""
+#define LDAP_NO_ATTRS "1.1"
+#define LDAP_ALL_USER_ATTRIBUTES "*"
+#define LDAP_ALL_OPERATIONAL_ATTRIBUTES "+" /* OpenLDAP extension */
+
+/*
+ * 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 /* deprecated */
+#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
+#define LDAP_OPT_MATCHED_DN 0x0033
+
+/* 0x34 - 0x0fff not defined by current draft */
+
+#define LDAP_OPT_PRIVATE_EXTENSION_BASE 0x4000 /* to 0x7FFF inclusive */
+
+/* private and experimental options */
+/* OpenLDAP specific options */
+#define LDAP_OPT_DEBUG_LEVEL 0x5001 /* debug level */
+#define LDAP_OPT_TIMEOUT 0x5002 /* default timeout */
+#define LDAP_OPT_REFHOPLIMIT 0x5003 /* ref hop limit */
+#define LDAP_OPT_NETWORK_TIMEOUT 0x5005 /* socket level timeout */
+#define LDAP_OPT_URI 0x5006
+
+/* OpenLDAP TLS options */
+#define LDAP_OPT_X_TLS 0x6000
+#define LDAP_OPT_X_TLS_CTX 0x6001 /* SSL CTX */
+#define LDAP_OPT_X_TLS_CACERTFILE 0x6002
+#define LDAP_OPT_X_TLS_CACERTDIR 0x6003
+#define LDAP_OPT_X_TLS_CERTFILE 0x6004
+#define LDAP_OPT_X_TLS_KEYFILE 0x6005
+#define LDAP_OPT_X_TLS_REQUIRE_CERT 0x6006
+/* #define LDAP_OPT_X_TLS_PROTOCOL 0x6007 */
+#define LDAP_OPT_X_TLS_CIPHER_SUITE 0x6008
+#define LDAP_OPT_X_TLS_RANDOM_FILE 0x6009
+
+#define LDAP_OPT_X_TLS_NEVER 0
+#define LDAP_OPT_X_TLS_HARD 1
+#define LDAP_OPT_X_TLS_DEMAND 2
+#define LDAP_OPT_X_TLS_ALLOW 3
+#define LDAP_OPT_X_TLS_TRY 4
+
+/* OpenLDAP SASL options */
+#define LDAP_OPT_X_SASL_MECH 0x6100
+#define LDAP_OPT_X_SASL_REALM 0x6101
+#define LDAP_OPT_X_SASL_AUTHCID 0x6102
+#define LDAP_OPT_X_SASL_AUTHZID 0x6103
+#define LDAP_OPT_X_SASL_SSF 0x6104 /* read-only */
+#define LDAP_OPT_X_SASL_SSF_EXTERNAL 0x6105 /* write-only */
+#define LDAP_OPT_X_SASL_SECPROPS 0x6106 /* write-only */
+#define LDAP_OPT_X_SASL_SSF_MIN 0x6107
+#define LDAP_OPT_X_SASL_SSF_MAX 0x6108
+#define LDAP_OPT_X_SASL_MAXBUFSIZE 0x6109
+
+
+/* on/off values */
+#define LDAP_OPT_ON ((void *) 1)
+#define LDAP_OPT_OFF ((void *) 0)
+
+/*
+ * ldap_get_option() and ldap_set_option() return values.
+ * As later versions may return other values indicating
+ * failure, current applications should only compare returned
+ * value against LDAP_OPT_SUCCESS.
+ */
+#define LDAP_OPT_SUCCESS 0
+#define LDAP_OPT_ERROR (-1)
+
+#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 */
+
+#define LDAP_CONTROL_MANAGEDSAIT "2.16.840.1.113730.3.4.2"
+
+#define LDAP_CONTROL_SORTREQUEST "1.2.840.113556.1.4.473"
+#define LDAP_CONTROL_SORTRESPONSE "1.2.840.113556.1.4.474"
+#define LDAP_CONTROL_VLVREQUEST "2.16.840.1.113730.3.4.9"
+#define LDAP_CONTROL_VLVRESPONSE "2.16.840.1.113730.3.4.10"
+
+/* LDAP Unsolicited Notifications */
+#define LDAP_NOTICE_OF_DISCONNECTION "1.3.6.1.4.1.1466.20036"
+#define LDAP_NOTICE_DISCONNECT LDAP_NOTICE_OF_DISCONNECTION
+
+/* LDAP Extended Operations */
+#define LDAP_EXOP_START_TLS "1.3.6.1.4.1.1466.20037"
+
+#define LDAP_EXOP_MODIFY_PASSWD "1.3.6.1.4.1.4203.1.11.1"
+#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U)
+#define LDAP_TAG_EXOP_MODIFY_PASSWD_OLD ((ber_tag_t) 0x81U)
+#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U)
+#define LDAP_TAG_EXOP_MODIFY_PASSWD_GEN ((ber_tag_t) 0x80U)
+
+#define LDAP_EXOP_X_WHO_AM_I "1.3.6.1.4.1.4203.1.11.3"
+
+/*
* 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) /* octet string */
+#define LDAP_TAG_LDAPCRED ((ber_tag_t) 0x04U) /* octet string */
+#define LDAP_TAG_CONTROLS ((ber_tag_t) 0xa0U) /* context specific + constructed + 0 */
+#define LDAP_TAG_REFERRAL ((ber_tag_t) 0xa3U) /* context specific + constructed + 3 */
+
+#define LDAP_TAG_NEWSUPERIOR ((ber_tag_t) 0x80U) /* context-specific + primitive + 0 */
+
+#define LDAP_TAG_EXOP_REQ_OID ((ber_tag_t) 0x80U) /* context specific + primitive */
+#define LDAP_TAG_EXOP_REQ_VALUE ((ber_tag_t) 0x81U) /* context specific + primitive */
+#define LDAP_TAG_EXOP_RES_OID ((ber_tag_t) 0x8aU) /* context specific + primitive */
+#define LDAP_TAG_EXOP_RES_VALUE ((ber_tag_t) 0x8bU) /* context specific + primitive */
+
+#define LDAP_TAG_SASL_RES_CREDS ((ber_tag_t) 0x87U) /* context specific + primitive */
+
/* 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
-
-/*
- * 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_REQ_BIND ((ber_tag_t) 0x60U) /* application + constructed */
+#define LDAP_REQ_UNBIND ((ber_tag_t) 0x42U) /* application + primitive */
+#define LDAP_REQ_SEARCH ((ber_tag_t) 0x63U) /* application + constructed */
+#define LDAP_REQ_MODIFY ((ber_tag_t) 0x66U) /* application + constructed */
+#define LDAP_REQ_ADD ((ber_tag_t) 0x68U) /* application + constructed */
+#define LDAP_REQ_DELETE ((ber_tag_t) 0x4aU) /* application + primitive */
+#define LDAP_REQ_MODDN ((ber_tag_t) 0x6cU) /* application + constructed */
+#define LDAP_REQ_MODRDN LDAP_REQ_MODDN
+#define LDAP_REQ_RENAME LDAP_REQ_MODDN
+#define LDAP_REQ_COMPARE ((ber_tag_t) 0x6eU) /* application + constructed */
+#define LDAP_REQ_ABANDON ((ber_tag_t) 0x50U) /* application + primitive */
+#define LDAP_REQ_EXTENDED ((ber_tag_t) 0x77U) /* application + constructed */
/* 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_MODDN ((ber_tag_t) 0x6dU) /* application + constructed */
+#define LDAP_RES_MODRDN LDAP_RES_MODDN /* application + constructed */
+#define LDAP_RES_RENAME LDAP_RES_MODDN /* application + constructed */
+#define LDAP_RES_COMPARE ((ber_tag_t) 0x6fU) /* application + constructed */
+#define LDAP_RES_EXTENDED ((ber_tag_t) 0x78U) /* V3: application + constructed */
+#define LDAP_RES_EXTENDED_PARTIAL ((ber_tag_t) 0x79U) /* V3+: application + constructed */
+
+#define LDAP_RES_ANY (-1)
+#define LDAP_RES_UNSOLICITED (0)
+
+
+/* sasl methods */
+#define LDAP_SASL_SIMPLE ((char*)0)
+#define LDAP_SASL_NULL ("")
+
/* authentication methods available */
-#define LDAP_AUTH_NONE 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 + constructed */
+#define LDAP_AUTH_KRBV4 ((ber_tag_t) 0xffU) /* means do both of the following */
+#define LDAP_AUTH_KRBV41 ((ber_tag_t) 0x81U) /* context specific + primitive */
+#define LDAP_AUTH_KRBV42 ((ber_tag_t) 0x82U) /* context specific + primitive */
+
/* 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_EXT ((ber_tag_t) 0xa9U) /* context specific + constructed */
+
+/* extended filter component types */
+#define LDAP_FILTER_EXT_OID ((ber_tag_t) 0x81U) /* context specific */
+#define LDAP_FILTER_EXT_TYPE ((ber_tag_t) 0x82U) /* context specific */
+#define LDAP_FILTER_EXT_VALUE ((ber_tag_t) 0x83U) /* context specific */
+#define LDAP_FILTER_EXT_DNATTRS ((ber_tag_t) 0x84U) /* context specific */
/* substring filter component types */
-#define LDAP_SUBSTRING_INITIAL 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_DEFAULT ((ber_int_t) -1)
+#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
- char *mod_type;
- union {
- 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;
+/* substring filter component types */
+#define LDAP_SUBSTRING_INITIAL ((ber_tag_t) 0x80U) /* context specific */
+#define LDAP_SUBSTRING_ANY ((ber_tag_t) 0x81U) /* context specific */
+#define LDAP_SUBSTRING_FINAL ((ber_tag_t) 0x82U) /* context specific */
-/*
+/*
* possible error codes we can return
*/
+#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 /* LDAPv2+ (not LDAPv3) */
+
+#define LDAP_REFERRAL 0x0a /* LDAPv3 */
+#define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* LDAPv3 */
+#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* LDAPv3 */
+#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* LDAPv3 */
+#define LDAP_SASL_BIND_IN_PROGRESS 0x0e /* LDAPv3 */
+
+#define LDAP_ATTR_ERROR(n) LDAP_RANGE((n),0x10,0x15) /* 16-21 */
#define LDAP_NO_SUCH_ATTRIBUTE 0x10
#define LDAP_UNDEFINED_TYPE 0x11
#define LDAP_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,0x61) /* 81-97 */
+#define LDAP_API_RESULT(n) (((n) == LDAP_SUCCESS) || \
+ LDAP_RANGE((n),0x51,0x61)) /* 0,81-97 */
+
+/* reserved for APIs */
#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
+/* used but not reserved for APIs */
+#define LDAP_CONNECT_ERROR 0x5b /* draft-ietf-ldap-c-api-xx */
+#define LDAP_NOT_SUPPORTED 0x5c /* draft-ietf-ldap-c-api-xx */
+#define LDAP_CONTROL_NOT_FOUND 0x5d /* draft-ietf-ldap-c-api-xx */
+#define LDAP_NO_RESULTS_RETURNED 0x5e /* draft-ietf-ldap-c-api-xx */
+#define LDAP_MORE_RESULTS_TO_RETURN 0x5f /* draft-ietf-ldap-c-api-xx */
+#define LDAP_CLIENT_LOOP 0x60 /* draft-ietf-ldap-c-api-xx */
+#define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61 /* draft-ietf-ldap-c-api-xx */
/*
* 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;
+
+/* for modifications */
+typedef struct ldapmod {
+ int mod_op;
+
+#define LDAP_MOD_ADD ((ber_int_t) 0x0000)
+#define LDAP_MOD_DELETE ((ber_int_t) 0x0001)
+#define LDAP_MOD_REPLACE ((ber_int_t) 0x0002)
+#define LDAP_MOD_BVALUES ((ber_int_t) 0x0080)
+/* IMPORTANT: do not use code 0x1000 (or above),
+ * it is used internally by the backends!
+ * (see ldap/servers/slapd/slap.h)
+ */
+
+ char *mod_type;
+ union mod_vals_u {
+ char **modv_strvals;
+ struct berval **modv_bvals;
+ } mod_vals;
+#define mod_values mod_vals.modv_strvals
+#define mod_bvalues mod_vals.modv_bvals
+} LDAPMod;
/*
* structures for ldap getfilter routines
typedef struct ldap_filt_info {
char *lfi_filter;
char *lfi_desc;
- int lfi_scope; /* LDAP_SCOPE_BASE, etc */
- int lfi_isexact; /* exact match filter? */
+ int lfi_scope;
+ int lfi_isexact;
struct ldap_filt_info *lfi_next;
} LDAPFiltInfo;
/*
- * structure representing an ldap connection
+ * structure representing an ldap session which can
+ * encompass connections to multiple servers (in the
+ * face of referrals).
*/
+typedef struct ldap LDAP;
-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
+#define LDAP_DEREF_NEVER 0x00
+#define LDAP_DEREF_SEARCHING 0x01
+#define LDAP_DEREF_FINDING 0x02
+#define LDAP_DEREF_ALWAYS 0x03
- int ld_timelimit;
- int ld_sizelimit;
#define LDAP_NO_LIMIT 0
- LDAPFiltDesc *ld_filtd; /* from getfilter for ufn searches */
- char *ld_ufnprefix; /* for incomplete ufn's */
+/* how many messages to retrieve results for */
+#define LDAP_MSG_ONE 0x00
+#define LDAP_MSG_ALL 0x01
+#define LDAP_MSG_RECEIVED 0x02
- int ld_errno;
- char *ld_error;
- char *ld_matched;
- int ld_msgid;
+/*
+ * types for ldap URL handling
+ */
+typedef struct ldap_url_desc {
+ struct ldap_url_desc *lud_next;
+ char *lud_scheme;
+ char *lud_host;
+ int lud_port;
+ char *lud_dn;
+ char **lud_attrs;
+ int lud_scope;
+ char *lud_filter;
+ char **lud_exts;
+ int lud_crit_exts;
+} LDAPURLDesc;
- /* 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 */
+#define LDAP_URL_SUCCESS 0x00 /* Success */
+#define LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */
+#define LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */
- /* 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 */
+#define LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */
+#define LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */
+#define LDAP_URL_ERR_BADURL 0x05 /* URL is bad */
+#define LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */
+#define LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */
+#define LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */
+#define LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */
+#define LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */
- /* 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;
+/*
+ * The API draft spec says we should declare (or cause to be declared)
+ * 'struct timeval'. We don't. See IETF LDAPext discussions.
+ */
+struct timeval;
+/*
+ * in options.c:
+ */
+LDAP_F( int )
+ldap_get_option LDAP_P((
+ LDAP *ld,
+ int option,
+ void *outvalue));
+
+LDAP_F( int )
+ldap_set_option LDAP_P((
+ LDAP *ld,
+ int option,
+ LDAP_CONST void *invalue));
+
+/* V3 REBIND Function Callback Prototype */
+typedef int (LDAP_REBIND_PROC) LDAP_P((
+ LDAP *ld, LDAP_CONST char *url,
+ ber_tag_t request, ber_int_t msgid,
+ void *params ));
+
+LDAP_F( int )
+ldap_set_rebind_proc LDAP_P((
+ LDAP *ld,
+ LDAP_REBIND_PROC *rebind_proc,
+ void *params ));
/*
- * structure for ldap friendly mapping routines
+ * in controls.c:
*/
+LDAP_F( int )
+ldap_create_control LDAP_P((
+ LDAP_CONST char *requestOID,
+ BerElement *ber,
+ int iscritical,
+ LDAPControl **ctrlp ));
-typedef struct friendly {
- char *f_unfriendly;
- char *f_friendly;
-} FriendlyMap;
+LDAP_F( void )
+ldap_control_free LDAP_P((
+ LDAPControl *ctrl ));
+LDAP_F( void )
+ldap_controls_free LDAP_P((
+ LDAPControl **ctrls ));
/*
- * handy macro to check whether LDAP struct is set up for CLDAP or not
+ * in dnssrv.c:
*/
-#define LDAP_IS_CLDAP( ld ) ( ld->ld_sb.sb_naddr > 0 )
+LDAP_F( int )
+ldap_domain2dn LDAP_P((
+ LDAP_CONST char* domain,
+ char** dn ));
+LDAP_F( int )
+ldap_dn2domain LDAP_P((
+ LDAP_CONST char* dn,
+ char** domain ));
+
+LDAP_F( int )
+ldap_domain2hostlist LDAP_P((
+ LDAP_CONST char *domain,
+ char** hostlist ));
/*
- * types for ldap URL handling
+ * in extended.c:
*/
-typedef struct ldap_url_desc {
- char *lud_host;
- int lud_port;
- char *lud_dn;
- char **lud_attrs;
- int lud_scope;
- 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
+LDAP_F( int )
+ldap_extended_operation LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *reqoid,
+ struct berval *reqdata,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_extended_operation_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *reqoid,
+ struct berval *reqdata,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ char **retoidp,
+ struct berval **retdatap ));
+
+LDAP_F( int )
+ldap_parse_extended_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ char **retoidp,
+ struct berval **retdatap,
+ int freeit ));
+
+LDAP_F( int )
+ldap_parse_extended_partial LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ char **retoidp,
+ struct berval **retdatap,
+ LDAPControl ***serverctrls,
+ int freeit ));
-#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
+/*
+ * in abandon.c:
+ */
+LDAP_F( int )
+ldap_abandon_ext LDAP_P((
+ LDAP *ld,
+ int msgid,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
-#ifdef VMS
-extern char *strdup( const char *s );
-#endif
-#if defined(ultrix) || defined( nextstep )
-extern char *strdup();
-#endif
+LDAP_F( int )
+ldap_abandon LDAP_P(( /* deprecated */
+ LDAP *ld,
+ int msgid ));
-#endif /* NEEDPROTOS */
-#ifdef __cplusplus
-}
-#endif
+/*
+ * in add.c:
+ */
+LDAP_F( int )
+ldap_add_ext LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_add_ext_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+LDAP_F( int )
+ldap_add LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **attrs ));
+
+LDAP_F( int )
+ldap_add_s LDAP_P(( /* deprecated */
+ 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 ));
+
+/* Interaction flags (should be passed about in a control)
+ * Automatic (default): use defaults, prompt otherwise
+ * Interactive: prompt always
+ * Quiet: never prompt
+ */
+#define LDAP_SASL_AUTOMATIC 0U
+#define LDAP_SASL_INTERACTIVE 1U
+#define LDAP_SASL_QUIET 2U
+
+/*
+ * V3 SASL Interaction Function Callback Prototype
+ * when using Cyrus SASL, interact is pointer to sasl_interact_t
+ * should likely passed in a control (and provided controls)
+ */
+typedef int (LDAP_SASL_INTERACT_PROC) LDAP_P((
+ LDAP *ld, unsigned flags, void* defaults, void *interact ));
+
+LDAP_F( int )
+ldap_sasl_interactive_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn, /* usually NULL */
+ LDAP_CONST char *saslMechanism,
+ LDAPControl **serverControls,
+ LDAPControl **clientControls,
+
+ /* should be client controls */
+ unsigned flags,
+ LDAP_SASL_INTERACT_PROC *proc,
+ void *defaults ));
+
+LDAP_F( int )
+ldap_sasl_bind_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *mechanism,
+ struct berval *cred,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls,
+ struct berval **servercredp ));
+
+LDAP_F( int )
+ldap_parse_sasl_bind_result LDAP_P((
+ LDAP *ld,
+ LDAPMessage *res,
+ struct berval **servercredp,
+ int freeit ));
+
+/*
+ * in bind.c:
+ * (deprecated)
+ */
+LDAP_F( int )
+ldap_bind LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *passwd,
+ int authmethod ));
+
+LDAP_F( int )
+ldap_bind_s LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *who,
+ LDAP_CONST char *cred,
+ int authmethod ));
+
+/*
+ * 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(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind1 LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind1_s LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind2 LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *who ));
+
+LDAP_F( int )
+ldap_kerberos_bind2_s LDAP_P(( /* deprecated */
+ 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(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *attr,
+ LDAP_CONST char *value ));
+
+LDAP_F( int )
+ldap_compare_s LDAP_P(( /* deprecated */
+ 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(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn ));
+
+LDAP_F( int )
+ldap_delete_s LDAP_P(( /* deprecated */
+ 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(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods ));
+
+LDAP_F( int )
+ldap_modify_s LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAPMod **mods ));
+
+
+/*
+ * in modrdn.c:
+ */
+LDAP_F( int )
+ldap_rename LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newSuperior,
+ int deleteoldrdn,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls,
+ int *msgidp ));
+
+LDAP_F( int )
+ldap_rename_s LDAP_P((
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newSuperior,
+ int deleteoldrdn,
+ LDAPControl **sctrls,
+ LDAPControl **cctrls ));
+
+LDAP_F( int )
+ldap_rename2 LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newSuperior,
+ int deleteoldrdn ));
+
+LDAP_F( int )
+ldap_rename2_s LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ LDAP_CONST char *newSuperior,
+ int deleteoldrdn ));
+
+LDAP_F( int )
+ldap_modrdn LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn ));
+
+LDAP_F( int )
+ldap_modrdn_s LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn ));
+
+LDAP_F( int )
+ldap_modrdn2 LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn ));
+
+LDAP_F( int )
+ldap_modrdn2_s LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *dn,
+ LDAP_CONST char *newrdn,
+ int deleteoldrdn));
+
+
+/*
+ * in open.c:
+ */
+LDAP_F( LDAP * )
+ldap_init LDAP_P((
+ LDAP_CONST char *host,
+ int port ));
+
+LDAP_F( LDAP * )
+ldap_open LDAP_P(( /* deprecated */
+ LDAP_CONST char *host,
+ int port ));
+
+LDAP_F( int )
+ldap_create LDAP_P((
+ LDAP **ldp ));
+
+LDAP_F( int )
+ldap_initialize LDAP_P((
+ LDAP **ldp,
+ LDAP_CONST char *url ));
+
+LDAP_F( int )
+ldap_start_tls_s LDAP_P((
+ LDAP *ld,
+ LDAPControl **serverctrls,
+ LDAPControl **clientctrls ));
+
+/*
+ * in messages.c:
+ */
+LDAP_F( LDAPMessage * )
+ldap_first_message LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage * )
+ldap_next_message LDAP_P((
+ LDAP *ld,
+ LDAPMessage *msg ));
+
+LDAP_F( int )
+ldap_count_messages LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+
+/*
+ * in references.c:
+ */
+LDAP_F( LDAPMessage * )
+ldap_first_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage * )
+ldap_next_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *ref ));
+
+LDAP_F( int )
+ldap_count_references LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( int )
+ldap_parse_reference LDAP_P((
+ LDAP *ld,
+ LDAPMessage *ref,
+ char ***referralsp,
+ LDAPControl ***serverctrls,
+ int freeit));
+
+
+/*
+ * in getentry.c:
+ */
+LDAP_F( LDAPMessage * )
+ldap_first_entry LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( LDAPMessage * )
+ldap_next_entry LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry ));
+
+LDAP_F( int )
+ldap_count_entries LDAP_P((
+ LDAP *ld,
+ LDAPMessage *chain ));
+
+LDAP_F( int )
+ldap_get_entry_controls LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAPControl ***serverctrls));
+
+
+/*
+ * in addentry.c
+ */
+LDAP_F( LDAPMessage * )
+ldap_delete_result_entry LDAP_P((
+ LDAPMessage **list,
+ LDAPMessage *e ));
+
+LDAP_F( void )
+ldap_add_result_entry LDAP_P((
+ LDAPMessage **list,
+ LDAPMessage *e ));
+
+
+/*
+ * in getdn.c
+ */
+LDAP_F( char * )
+ldap_get_dn LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry ));
+
+typedef struct ldap_ava {
+ struct berval la_attr;
+ struct berval la_value;
+ unsigned la_flags;
+#define LDAP_AVA_STRING 0x0000U
+#define LDAP_AVA_BINARY 0x0001U
+#define LDAP_AVA_NONPRINTABLE 0x0002U
+
+ void *la_private;
+} LDAPAVA;
+
+typedef LDAPAVA** LDAPRDN;
+typedef LDAPRDN** LDAPDN;
+
+/* DN formats */
+#define LDAP_DN_FORMAT_LDAP 0x0000U
+#define LDAP_DN_FORMAT_LDAPV3 0x0010U
+#define LDAP_DN_FORMAT_LDAPV2 0x0020U
+#define LDAP_DN_FORMAT_DCE 0x0030U
+#define LDAP_DN_FORMAT_UFN 0x0040U /* dn2str only */
+#define LDAP_DN_FORMAT_AD_CANONICAL 0x0050U /* dn2str only */
+#define LDAP_DN_FORMAT_LBER 0x00F0U /* for testing only */
+#define LDAP_DN_FORMAT_MASK 0x00F0U
+
+/* DN flags */
+#define LDAP_DN_PRETTY 0x0100U
+#define LDAP_DN_SKIP 0x0200U
+#define LDAP_DN_P_NOLEADTRAILSPACES 0x1000U
+#define LDAP_DN_P_NOSPACEAFTERRDN 0x2000U
+#define LDAP_DN_PEDANTIC 0xF000U
+
+LDAP_F( void )
+ldap_avafree LDAP_P(( LDAPAVA *ava ));
+LDAP_F( void )
+ldap_rdnfree LDAP_P(( LDAPRDN *rdn ));
+LDAP_F( void )
+ldap_dnfree LDAP_P(( LDAPDN *dn ));
+
+LDAP_F( int )
+ldap_bv2dn LDAP_P((
+ struct berval *bv,
+ LDAPDN **dn,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_str2dn LDAP_P((
+ LDAP_CONST char *str,
+ LDAPDN **dn,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_dn2bv LDAP_P((
+ LDAPDN *dn,
+ struct berval *bv,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_dn2str LDAP_P((
+ LDAPDN *dn,
+ char **str,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_bv2rdn LDAP_P((
+ struct berval *bv,
+ LDAPRDN **rdn,
+ char **next,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_str2rdn LDAP_P((
+ LDAP_CONST char *str,
+ LDAPRDN **rdn,
+ char **next,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_rdn2bv LDAP_P((
+ LDAPRDN *rdn,
+ struct berval *bv,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_rdn2str LDAP_P((
+ LDAPRDN *rdn,
+ char **str,
+ unsigned flags ));
+
+LDAP_F( int )
+ldap_dn_normalize LDAP_P((
+ LDAP_CONST char *in, unsigned iflags,
+ char **out, unsigned oflags ));
+
+LDAP_F( char * )
+ldap_dn2ufn LDAP_P(( /* deprecated */
+ LDAP_CONST char *dn ));
+
+LDAP_F( char ** )
+ldap_explode_dn LDAP_P(( /* deprecated */
+ LDAP_CONST char *dn,
+ int notypes ));
+
+LDAP_F( char ** )
+ldap_explode_rdn LDAP_P(( /* deprecated */
+ LDAP_CONST char *rdn,
+ int notypes ));
+
+LDAP_F( char * )
+ldap_dn2dcedn LDAP_P(( LDAP_CONST char *dn )); /* deprecated */
+
+LDAP_F( char * )
+ldap_dcedn2dn LDAP_P(( LDAP_CONST char *dce )); /* deprecated */
+
+LDAP_F( char * )
+ldap_dn2ad_canonical LDAP_P(( LDAP_CONST char *dn )); /* deprecated */
+
+/*
+ * in getattr.c
+ */
+LDAP_F( char * )
+ldap_first_attribute LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement **ber ));
+
+LDAP_F( char * )
+ldap_next_attribute LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ BerElement *ber ));
+
+
+/*
+ * in getvalues.c
+ */
+LDAP_F( struct berval ** )
+ldap_get_values_len LDAP_P((
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAP_CONST char *target ));
+
+LDAP_F( int )
+ldap_count_values_len LDAP_P((
+ struct berval **vals ));
+
+LDAP_F( void )
+ldap_value_free_len LDAP_P((
+ struct berval **vals ));
+
+LDAP_F( char ** )
+ldap_get_values LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAPMessage *entry,
+ LDAP_CONST char *target ));
+
+LDAP_F( int )
+ldap_count_values LDAP_P(( /* deprecated */
+ char **vals ));
+
+LDAP_F( void )
+ldap_value_free LDAP_P(( /* deprecated */
+ char **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(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly ));
+
+LDAP_F( int )
+ldap_search_s LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ LDAPMessage **res ));
+
+LDAP_F( int )
+ldap_search_st LDAP_P(( /* deprecated */
+ LDAP *ld,
+ LDAP_CONST char *base,
+ int scope,
+ LDAP_CONST char *filter,
+ char **attrs,
+ int attrsonly,
+ struct timeval *timeout,
+ LDAPMessage **res ));
+
+/*
+ * in unbind.c
+ */
+LDAP_F( int )
+ldap_unbind LDAP_P(( /* deprecated */
+ LDAP *ld ));
+
+LDAP_F( int )
+ldap_unbind_s LDAP_P(( /* deprecated */
+ 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
+ * (deprecated)
+ */
+LDAP_F( LDAPFiltDesc * )
+ldap_init_getfilter LDAP_P(( /* deprecated */
+ LDAP_CONST char *fname ));
+
+LDAP_F( LDAPFiltInfo * )
+ldap_getfirstfilter LDAP_P(( /* deprecated */
+ LDAPFiltDesc *lfdp,
+ /* LDAP_CONST */ char *tagpat,
+ /* LDAP_CONST */ char *value ));
+
+LDAP_F( LDAPFiltInfo * )
+ldap_getnextfilter LDAP_P(( /* deprecated */
+ LDAPFiltDesc *lfdp ));
+
+
+/*
+ * 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 sort.c
+ * (deprecated)
+ */
+typedef int (LDAP_SORT_AD_CMP_PROC) LDAP_P(( /* deprecated */
+ LDAP_CONST char *left,
+ LDAP_CONST char *right ));
+
+typedef int (LDAP_SORT_AV_CMP_PROC) LDAP_P(( /* deprecated */
+ LDAP_CONST void *left,
+ LDAP_CONST void *right ));
+
+LDAP_F( int ) /* deprecated */
+ldap_sort_entries LDAP_P(( LDAP *ld,
+ LDAPMessage **chain,
+ LDAP_CONST char *attr,
+ LDAP_SORT_AD_CMP_PROC *cmp ));
+
+LDAP_F( int ) /* deprecated */
+ldap_sort_values LDAP_P((
+ LDAP *ld,
+ char **vals,
+ LDAP_SORT_AV_CMP_PROC *cmp ));
+
+LDAP_F( int ) /* deprecated */
+ldap_sort_strcasecmp LDAP_P((
+ LDAP_CONST void *a,
+ LDAP_CONST void *b ));
+
+
+/*
+ * in url.c
+ */
+LDAP_F( int )
+ldap_is_ldap_url LDAP_P((
+ LDAP_CONST char *url ));
+
+LDAP_F( int )
+ldap_is_ldaps_url LDAP_P((
+ LDAP_CONST char *url ));
+
+LDAP_F( int )
+ldap_is_ldapi_url LDAP_P((
+ LDAP_CONST char *url ));
+
+LDAP_F( int )
+ldap_url_parse LDAP_P((
+ LDAP_CONST char *url,
+ LDAPURLDesc **ludpp ));
+
+LDAP_F( char * )
+ldap_url_desc2str LDAP_P((
+ LDAPURLDesc *ludp ));
+
+LDAP_F( void )
+ldap_free_urldesc LDAP_P((
+ LDAPURLDesc *ludp ));
+
+/*
+ * in sortctrl.c
+ */
+/*
+ * structure for a sort-key
+ */
+typedef struct ldapsortkey {
+ char * attributeType;
+ char * orderingRule;
+ int reverseOrder;
+} LDAPSortKey;
+
+LDAP_F( int )
+ldap_create_sort_keylist LDAP_P((
+ LDAPSortKey ***sortKeyList,
+ char *keyString ));
+
+LDAP_F( void )
+ldap_free_sort_keylist LDAP_P((
+ LDAPSortKey **sortkeylist ));
+
+LDAP_F( int )
+ldap_create_sort_control LDAP_P((
+ LDAP *ld,
+ LDAPSortKey **keyList,
+ int ctl_iscritical,
+ LDAPControl **ctrlp ));
+
+LDAP_F( int )
+ldap_parse_sort_control LDAP_P((
+ LDAP *ld,
+ LDAPControl **ctrlp,
+ unsigned long *result,
+ char **attribute ));
+
+
+/*
+ * in vlvctrl.c
+ */
+
+/*
+ * structure for virtul list.
+ */
+typedef struct ldapvlvinfo {
+ int ldvlv_version;
+ unsigned long ldvlv_before_count;
+ unsigned long ldvlv_after_count;
+ unsigned long ldvlv_offset;
+ unsigned long ldvlv_count;
+ struct berval *ldvlv_attrvalue;
+ struct berval *ldvlv_context;
+ void *ldvlv_extradata;
+} LDAPVLVInfo;
+
+LDAP_F( int )
+ldap_create_vlv_control LDAP_P((
+ LDAP *ld,
+ LDAPVLVInfo *ldvlistp,
+ LDAPControl **ctrlp ));
+
+LDAP_F( int )
+ldap_parse_vlv_control LDAP_P((
+ LDAP *ld,
+ LDAPControl **ctrls,
+ unsigned long *target_posp,
+ unsigned long *list_countp,
+ struct berval **contextp,
+ int *errcodep ));
+
+
+LDAP_END_DECL
#endif /* _LDAP_H */
--- /dev/null
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* at.c - routines for dealing with attribute types */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/socket.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap_pvt.h"
+#include "slap.h"
+
+
+int is_at_syntax(
+ AttributeType *at,
+ const char *oid )
+{
+ for( ; at != NULL; at = at->sat_sup ) {
+ if( at->sat_syntax_oid ) {
+ return ( strcmp( at->sat_syntax_oid, oid ) == 0 );
+ }
+ }
+
+ return 0;
+}
+
+int is_at_subtype(
+ AttributeType *sub,
+ AttributeType *sup )
+{
+ for( ; sub != NULL; sub = sub->sat_sup ) {
+ if( sub == sup ) return 1;
+ }
+
+ return 0;
+}
+
+struct aindexrec {
+ struct berval air_name;
+ AttributeType *air_at;
+};
+
+static Avlnode *attr_index = NULL;
+static AttributeType *attr_list = NULL;
+
+static int
+attr_index_cmp(
+ struct aindexrec *air1,
+ struct aindexrec *air2
+)
+{
+ int i = air1->air_name.bv_len - air2->air_name.bv_len;
+ if (i)
+ return i;
+ return (strcasecmp( air1->air_name.bv_val, air2->air_name.bv_val ));
+}
+
+static int
+attr_index_name_cmp(
+ struct berval *type,
+ struct aindexrec *air
+)
+{
+ int i = type->bv_len - air->air_name.bv_len;
+ if (i)
+ return i;
+ return (strncasecmp( type->bv_val, air->air_name.bv_val,
+ type->bv_len ));
+}
+
+AttributeType *
+at_find(
+ const char *name
+)
+{
+ struct berval bv;
+
+ bv.bv_val = (char *)name;
+ bv.bv_len = strlen( name );
+
+ return at_bvfind( &bv );
+}
+
+AttributeType *
+at_bvfind(
+ struct berval *name
+)
+{
+ struct aindexrec *air;
+
+ air = (struct aindexrec *) avl_find( attr_index, name,
+ (AVL_CMP) attr_index_name_cmp );
+
+ return air != NULL ? air->air_at : NULL;
+}
+
+int
+at_append_to_list(
+ AttributeType *sat,
+ AttributeType ***listp
+)
+{
+ AttributeType **list;
+ AttributeType **list1;
+ int size;
+
+ list = *listp;
+ if ( !list ) {
+ size = 2;
+ list = ch_calloc(size, sizeof(AttributeType *));
+ if ( !list ) {
+ return -1;
+ }
+ } else {
+ size = 0;
+ list1 = *listp;
+ while ( *list1 ) {
+ size++;
+ list1++;
+ }
+ size += 2;
+ list1 = ch_realloc(list, size*sizeof(AttributeType *));
+ if ( !list1 ) {
+ return -1;
+ }
+ list = list1;
+ }
+ list[size-2] = sat;
+ list[size-1] = NULL;
+ *listp = list;
+ return 0;
+}
+
+int
+at_delete_from_list(
+ int pos,
+ AttributeType ***listp
+)
+{
+ AttributeType **list;
+ AttributeType **list1;
+ int i;
+ int j;
+
+ if ( pos < 0 ) {
+ return -2;
+ }
+ list = *listp;
+ for ( i=0; list[i]; i++ )
+ ;
+ if ( pos >= i ) {
+ return -2;
+ }
+ for ( i=pos, j=pos+1; list[j]; i++, j++ ) {
+ list[i] = list[j];
+ }
+ list[i] = NULL;
+ /* Tell the runtime this can be shrinked */
+ list1 = ch_realloc(list, (i+1)*sizeof(AttributeType **));
+ if ( !list1 ) {
+ return -1;
+ }
+ *listp = list1;
+ return 0;
+}
+
+int
+at_find_in_list(
+ AttributeType *sat,
+ AttributeType **list
+)
+{
+ int i;
+
+ if ( !list ) {
+ return -1;
+ }
+ for ( i=0; list[i]; i++ ) {
+ if ( sat == list[i] ) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void
+at_destroy( void )
+{
+ AttributeType *a, *n;
+ avl_free(attr_index, ldap_memfree);
+
+ for (a=attr_list; a; a=n) {
+ n = a->sat_next;
+ if (a->sat_subtypes) ldap_memfree(a->sat_subtypes);
+ ad_destroy(a->sat_ad);
+ ldap_pvt_thread_mutex_destroy(&a->sat_ad_mutex);
+ ldap_attributetype_free((LDAPAttributeType *)a);
+ }
+ if ( slap_schema.si_at_undefined )
+ ad_destroy(slap_schema.si_at_undefined->sat_ad);
+}
+
+static int
+at_insert(
+ AttributeType *sat,
+ const char **err
+)
+{
+ AttributeType **atp;
+ struct aindexrec *air;
+ char **names;
+
+ atp = &attr_list;
+ while ( *atp != NULL ) {
+ atp = &(*atp)->sat_next;
+ }
+ *atp = sat;
+
+ if ( sat->sat_oid ) {
+ air = (struct aindexrec *)
+ ch_calloc( 1, sizeof(struct aindexrec) );
+ air->air_name.bv_val = sat->sat_oid;
+ air->air_name.bv_len = strlen(sat->sat_oid);
+ air->air_at = sat;
+ if ( avl_insert( &attr_index, (caddr_t) air,
+ (AVL_CMP) attr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = sat->sat_oid;
+ ldap_memfree(air);
+ return SLAP_SCHERR_DUP_ATTR;
+ }
+ /* FIX: temporal consistency check */
+ at_bvfind(&air->air_name);
+ }
+
+ if ( (names = sat->sat_names) ) {
+ while ( *names ) {
+ air = (struct aindexrec *)
+ ch_calloc( 1, sizeof(struct aindexrec) );
+ air->air_name.bv_val = *names;
+ air->air_name.bv_len = strlen(*names);
+ air->air_at = sat;
+ if ( avl_insert( &attr_index, (caddr_t) air,
+ (AVL_CMP) attr_index_cmp,
+ (AVL_DUP) avl_dup_error ) ) {
+ *err = *names;
+ ldap_memfree(air);
+ return SLAP_SCHERR_DUP_ATTR;
+ }
+ /* FIX: temporal consistency check */
+ at_bvfind(&air->air_name);
+ names++;
+ }
+ }
+
+ return 0;
+}
+
+int
+at_add(
+ LDAPAttributeType *at,
+ const char **err
+)
+{
+ AttributeType *sat;
+ MatchingRule *mr;
+ Syntax *syn;
+ int code;
+ char *cname;
+ char *oid;
+
+ if ( !OID_LEADCHAR( at->at_oid[0] )) {
+ /* Expand OID macros */
+ oid = oidm_find( at->at_oid );
+ if ( !oid ) {
+ *err = at->at_oid;
+ return SLAP_SCHERR_OIDM;
+ }
+ if ( oid != at->at_oid ) {
+ ldap_memfree( at->at_oid );
+ at->at_oid = oid;
+ }
+ }
+
+ if ( at->at_syntax_oid && !OID_LEADCHAR( at->at_syntax_oid[0] )) {
+ /* Expand OID macros */
+ oid = oidm_find( at->at_syntax_oid );
+ if ( !oid ) {
+ *err = at->at_syntax_oid;
+ return SLAP_SCHERR_OIDM;
+ }
+ if ( oid != at->at_syntax_oid ) {
+ ldap_memfree( at->at_syntax_oid );
+ at->at_syntax_oid = oid;
+ }
+
+ }
+
+ if ( at->at_names && at->at_names[0] ) {
+ int i;
+
+ for( i=0; at->at_names[i]; i++ ) {
+ if( !slap_valid_descr( at->at_names[i] ) ) {
+ *err = at->at_names[i];
+ return SLAP_SCHERR_BAD_DESCR;
+ }
+ }
+
+ cname = at->at_names[0];
+
+ } else if ( at->at_oid ) {
+ cname = at->at_oid;
+
+ } else {
+ *err = "";
+ return SLAP_SCHERR_ATTR_INCOMPLETE;
+ }
+
+ *err = cname;
+
+ if ( !at->at_usage && at->at_no_user_mod ) {
+ /* user attribute must be modifable */
+ return SLAP_SCHERR_ATTR_BAD_USAGE;
+ }
+
+ if ( at->at_collective ) {
+ if( at->at_usage ) {
+ /* collective attributes cannot be operational */
+ return SLAP_SCHERR_ATTR_BAD_USAGE;
+ }
+
+ if( at->at_single_value ) {
+ /* collective attributes cannot be single-valued */
+ return SLAP_SCHERR_ATTR_BAD_USAGE;
+ }
+
+ /* collective attributes not supported */
+ return SLAP_SCHERR_NOT_SUPPORTED;
+ }
+
+ sat = (AttributeType *) ch_calloc( 1, sizeof(AttributeType) );
+ AC_MEMCPY( &sat->sat_atype, at, sizeof(LDAPAttributeType));
+
+ sat->sat_cname.bv_val = cname;
+ sat->sat_cname.bv_len = strlen( cname );
+ ldap_pvt_thread_mutex_init(&sat->sat_ad_mutex);
+
+ if ( at->at_sup_oid ) {
+ AttributeType *supsat = at_find(at->at_sup_oid);
+
+ if ( (supsat == NULL ) ) {
+ *err = at->at_sup_oid;
+ return SLAP_SCHERR_ATTR_NOT_FOUND;
+ }
+
+ sat->sat_sup = supsat;
+
+ if ( at_append_to_list(sat, &supsat->sat_subtypes) ) {
+ return SLAP_SCHERR_OUTOFMEM;
+ }
+
+ if ( sat->sat_usage != supsat->sat_usage ) {
+ /* subtypes must have same usage as their SUP */
+ return SLAP_SCHERR_ATTR_BAD_USAGE;
+ }
+ }
+
+ /*
+ * Inherit definitions from superiors. We only check the
+ * direct superior since that one has already inherited from
+ * its own superiorss
+ */
+ if ( sat->sat_sup ) {
+ sat->sat_syntax = sat->sat_sup->sat_syntax;
+ sat->sat_equality = sat->sat_sup->sat_equality;
+ sat->sat_approx = sat->sat_sup->sat_approx;
+ sat->sat_ordering = sat->sat_sup->sat_ordering;
+ sat->sat_substr = sat->sat_sup->sat_substr;
+ }
+
+ if ( at->at_syntax_oid ) {
+ if ( (syn = syn_find(sat->sat_syntax_oid)) ) {
+ sat->sat_syntax = syn;
+ } else {
+ *err = sat->sat_syntax_oid;
+ return SLAP_SCHERR_SYN_NOT_FOUND;
+ }
+
+
+ } else if ( sat->sat_syntax == NULL ) {
+ return SLAP_SCHERR_ATTR_INCOMPLETE;
+ }
+
+ if ( sat->sat_equality_oid ) {
+ if ( (mr = mr_find(sat->sat_equality_oid)) ) {
+ sat->sat_equality = mr;
+ sat->sat_approx = mr->smr_associated;
+ } else {
+ *err = sat->sat_equality_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+
+ }
+
+ if ( sat->sat_ordering_oid ) {
+ if ( (mr = mr_find(sat->sat_ordering_oid)) ) {
+ sat->sat_ordering = mr;
+ } else {
+ *err = sat->sat_ordering_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+
+ if ( sat->sat_substr_oid ) {
+ if ( (mr = mr_find(sat->sat_substr_oid)) ) {
+ sat->sat_substr = mr;
+ } else {
+ *err = sat->sat_substr_oid;
+ return SLAP_SCHERR_MR_NOT_FOUND;
+ }
+ }
+
+ code = at_insert(sat,err);
+ return code;
+}
+
+#ifdef LDAP_DEBUG
+static int
+at_index_printnode( struct aindexrec *air )
+{
+
+ printf("%s = %s\n",
+ air->air_name.bv_val,
+ ldap_attributetype2str(&air->air_at->sat_atype) );
+ return( 0 );
+}
+
+static void
+at_index_print( void )
+{
+ printf("Printing attribute type index:\n");
+ (void) avl_apply( attr_index, (AVL_APPLY) at_index_printnode,
+ 0, -1, AVL_INORDER );
+}
+#endif
+
+#if defined( SLAPD_SCHEMA_DN )
+int
+at_schema_info( Entry *e )
+{
+ struct berval vals[2];
+ AttributeType *at;
+
+ AttributeDescription *ad_attributeTypes = slap_schema.si_ad_attributeTypes;
+
+ vals[1].bv_val = NULL;
+
+ for ( at = attr_list; at; at = at->sat_next ) {
+ if ( ldap_attributetype2bv( &at->sat_atype, vals ) == NULL ) {
+ return -1;
+ }
+#if 0
+ Debug( LDAP_DEBUG_TRACE, "Merging at [%ld] %s\n",
+ (long) vals[0].bv_len, vals[0].bv_val, 0 );
+#endif
+ attr_merge( e, ad_attributeTypes, vals );
+ ldap_memfree( vals[0].bv_val );
+ }
+ return 0;
+}
+#endif
--- /dev/null
+/* schema_init.c - init builtin schema */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <limits.h>
+
+#include <ac/ctype.h>
+#include <ac/errno.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "ldap_pvt.h"
+#include "lber_pvt.h"
+
+#include "ldap_utf8.h"
+
+#include "lutil_hash.h"
+#define HASH_BYTES LUTIL_HASH_BYTES
+#define HASH_CONTEXT lutil_HASH_CTX
+#define HASH_Init(c) lutil_HASHInit(c)
+#define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
+#define HASH_Final(d,c) lutil_HASHFinal(d,c)
+
+/* recycled validatation routines */
+#define berValidate blobValidate
+
+/* unimplemented pretters */
+#define integerPretty NULL
+
+/* recycled matching routines */
+#define bitStringMatch octetStringMatch
+#define numericStringMatch caseIgnoreIA5Match
+#define objectIdentifierMatch caseIgnoreIA5Match
+#define telephoneNumberMatch caseIgnoreIA5Match
+#define telephoneNumberSubstringsMatch caseIgnoreIA5SubstringsMatch
+#define generalizedTimeMatch caseIgnoreIA5Match
+#define generalizedTimeOrderingMatch caseIgnoreIA5Match
+#define uniqueMemberMatch dnMatch
+
+/* approx matching rules */
+#define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
+#define directoryStringApproxMatch approxMatch
+#define directoryStringApproxIndexer approxIndexer
+#define directoryStringApproxFilter approxFilter
+#define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
+#define IA5StringApproxMatch approxMatch
+#define IA5StringApproxIndexer approxIndexer
+#define IA5StringApproxFilter approxFilter
+
+/* orderring matching rules */
+#define caseIgnoreOrderingMatch caseIgnoreMatch
+#define caseExactOrderingMatch caseExactMatch
+
+/* unimplemented matching routines */
+#define caseIgnoreListMatch NULL
+#define caseIgnoreListSubstringsMatch NULL
+#define protocolInformationMatch NULL
+#define integerFirstComponentMatch NULL
+
+#ifdef SLAPD_ACI_ENABLED
+#define OpenLDAPaciMatch NULL
+#endif
+#ifdef SLAPD_AUTHPASSWD
+#define authPasswordMatch NULL
+#endif
+
+/* recycled indexing/filtering routines */
+#define dnIndexer caseExactIgnoreIndexer
+#define dnFilter caseExactIgnoreFilter
+#define bitStringFilter octetStringFilter
+#define bitStringIndexer octetStringIndexer
+
+#define telephoneNumberIndexer caseIgnoreIA5Indexer
+#define telephoneNumberFilter caseIgnoreIA5Filter
+#define telephoneNumberSubstringsIndexer caseIgnoreIA5SubstringsIndexer
+#define telephoneNumberSubstringsFilter caseIgnoreIA5SubstringsFilter
+
+/* must match OIDs below */
+#define caseExactMatchOID "2.5.13.5"
+#define caseExactSubstringsMatchOID "2.5.13.7"
+
+static char *bvcasechr( struct berval *bv, int c, ber_len_t *len )
+{
+ ber_len_t i;
+ int lower = TOLOWER( c );
+ int upper = TOUPPER( c );
+
+ if( c == 0 ) return NULL;
+
+ for( i=0; i < bv->bv_len; i++ ) {
+ if( upper == bv->bv_val[i] || lower == bv->bv_val[i] ) {
+ *len = i;
+ return &bv->bv_val[i];
+ }
+ }
+
+ return NULL;
+}
+
+static int
+octetStringMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
+
+ if( match == 0 ) {
+ match = memcmp( value->bv_val,
+ ((struct berval *) assertedValue)->bv_val,
+ value->bv_len );
+ }
+
+ *matchp = match;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int octetStringIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ int i;
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* just count them */
+ }
+
+ /* we should have at least one value at this point */
+ assert( i > 0 );
+
+ keys = ch_malloc( sizeof( struct berval ) * (i+1) );
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ values[i].bv_val, values[i].bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[i], &digest );
+ }
+
+ keys[i].bv_val = NULL;
+
+ *keysp = keys;
+
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int octetStringFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval *value = (struct berval *) assertValue;
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ keys = ch_malloc( sizeof( struct berval ) * 2 );
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value->bv_val, value->bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( keys, &digest );
+ keys[1].bv_val = NULL;
+
+ *keysp = keys;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+nameUIDValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int rc;
+ struct berval dn;
+
+ if( in->bv_len == 0 ) return LDAP_SUCCESS;
+
+ ber_dupbv( &dn, in );
+ if( !dn.bv_val ) return LDAP_OTHER;
+
+ if( dn.bv_val[dn.bv_len-1] == 'B'
+ && dn.bv_val[dn.bv_len-2] == '\'' )
+ {
+ /* assume presence of optional UID */
+ ber_len_t i;
+
+ for(i=dn.bv_len-3; i>1; i--) {
+ if( dn.bv_val[i] != '0' && dn.bv_val[i] != '1' ) {
+ break;
+ }
+ }
+ if( dn.bv_val[i] != '\'' ||
+ dn.bv_val[i-1] != '#' ) {
+ ber_memfree( dn.bv_val );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* trim the UID to allow use of dnValidate */
+ dn.bv_val[i-1] = '\0';
+ dn.bv_len = i-1;
+ }
+
+ rc = dnValidate( NULL, &dn );
+
+ ber_memfree( &dn );
+ return rc;
+}
+
+static int
+nameUIDNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ struct berval out;
+ int rc;
+
+ ber_dupbv( &out, val );
+ if( out.bv_len != 0 ) {
+ ber_len_t dnlen;
+ char *uid = NULL;
+ ber_len_t uidlen = 0;
+
+ if( out.bv_val[out.bv_len-1] == '\'' ) {
+ /* assume presence of optional UID */
+ uid = strrchr( out.bv_val, '#' );
+
+ if( uid == NULL ) {
+ free( out.bv_val );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ uidlen = out.bv_len - (uid - out.bv_val);
+ /* temporarily trim the UID */
+ *uid = '\0';
+ out.bv_len -= uidlen;
+ }
+
+#ifdef USE_DN_NORMALIZE
+ rc = dnNormalize2( NULL, &out, normalized );
+#else
+ rc = dnPretty2( NULL, &out, normalized );
+#endif
+
+ if( rc != LDAP_SUCCESS ) {
+ free( out.bv_val );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ dnlen = normalized->bv_len;
+
+ if( uidlen ) {
+ struct berval b2;
+ b2.bv_val = ch_malloc(dnlen + uidlen + 1);
+ AC_MEMCPY( b2.bv_val, normalized->bv_val, dnlen );
+
+ /* restore the separator */
+ *uid = '#';
+ /* shift the UID */
+ AC_MEMCPY( normalized->bv_val+dnlen, uid, uidlen );
+ b2.bv_len = dnlen + uidlen;
+ normalized->bv_val[dnlen+uidlen] = '\0';
+ free(normalized->bv_val);
+ *normalized = b2;
+ }
+ free( out.bv_val );
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+inValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ /* any value allowed */
+ return LDAP_OTHER;
+}
+
+static int
+blobValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ /* any value allowed */
+ return LDAP_SUCCESS;
+}
+
+static int
+bitStringValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ ber_len_t i;
+
+ /* very unforgiving validation, requires no normalization
+ * before simplistic matching
+ */
+ if( in->bv_len < 3 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /*
+ * rfc 2252 section 6.3 Bit String
+ * bitstring = "'" *binary-digit "'"
+ * binary-digit = "0" / "1"
+ * example: '0101111101'B
+ */
+
+ if( in->bv_val[0] != '\'' ||
+ in->bv_val[in->bv_len-2] != '\'' ||
+ in->bv_val[in->bv_len-1] != 'B' )
+ {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for( i=in->bv_len-3; i>0; i-- ) {
+ if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+bitStringNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ /*
+ * A normalized bitString is has no extaneous (leading) zero bits.
+ * That is, '00010'B is normalized to '10'B
+ * However, as a special case, '0'B requires no normalization.
+ */
+ char *p;
+
+ /* start at the first bit */
+ p = &val->bv_val[1];
+
+ /* Find the first non-zero bit */
+ while ( *p == '0' ) p++;
+
+ if( *p == '\'' ) {
+ /* no non-zero bits */
+ ber_str2bv( "\'0\'B", sizeof("\'0\'B") - 1, 1, normalized );
+ goto done;
+ }
+
+ normalized->bv_val = ch_malloc( val->bv_len + 1 );
+
+ normalized->bv_val[0] = '\'';
+ normalized->bv_len = 1;
+
+ for( ; *p != '\0'; p++ ) {
+ normalized->bv_val[normalized->bv_len++] = *p;
+ }
+
+ normalized->bv_val[normalized->bv_len] = '\0';
+
+done:
+ return LDAP_SUCCESS;
+}
+
+/*
+ * Handling boolean syntax and matching is quite rigid.
+ * A more flexible approach would be to allow a variety
+ * of strings to be normalized and prettied into TRUE
+ * and FALSE.
+ */
+static int
+booleanValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ /* very unforgiving validation, requires no normalization
+ * before simplistic matching
+ */
+
+ if( in->bv_len == 4 ) {
+ if( !memcmp( in->bv_val, "TRUE", 4 ) ) {
+ return LDAP_SUCCESS;
+ }
+ } else if( in->bv_len == 5 ) {
+ if( !memcmp( in->bv_val, "FALSE", 5 ) ) {
+ return LDAP_SUCCESS;
+ }
+ }
+
+ return LDAP_INVALID_SYNTAX;
+}
+
+static int
+booleanMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ /* simplistic matching allowed by rigid validation */
+ struct berval *asserted = (struct berval *) assertedValue;
+ *matchp = value->bv_len != asserted->bv_len;
+ return LDAP_SUCCESS;
+}
+
+static int
+UTF8StringValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ ber_len_t count;
+ int len;
+ unsigned char *u = in->bv_val;
+
+ if( !in->bv_len ) return LDAP_INVALID_SYNTAX;
+
+ for( count = in->bv_len; count > 0; count-=len, u+=len ) {
+ /* get the length indicated by the first byte */
+ len = LDAP_UTF8_CHARLEN2( u, len );
+
+ /* very basic checks */
+ switch( len ) {
+ case 6:
+ if( (u[5] & 0xC0) != 0x80 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ case 5:
+ if( (u[4] & 0xC0) != 0x80 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ case 4:
+ if( (u[3] & 0xC0) != 0x80 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ case 3:
+ if( (u[2] & 0xC0 )!= 0x80 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ case 2:
+ if( (u[1] & 0xC0) != 0x80 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ case 1:
+ /* CHARLEN already validated it */
+ break;
+ default:
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* make sure len corresponds with the offset
+ to the next character */
+ if( LDAP_UTF8_OFFSET( u ) != len ) return LDAP_INVALID_SYNTAX;
+ }
+
+ if( count != 0 ) return LDAP_INVALID_SYNTAX;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+UTF8StringNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ char *p, *q, *s, *e;
+ int len = 0;
+
+ p = val->bv_val;
+
+ /* Ignore initial whitespace */
+ /* All space is ASCII. All ASCII is 1 byte */
+ for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ );
+
+ ber_mem2bv( p, val->bv_len - (p - val->bv_val), 1, normalized );
+ e = normalized->bv_val + val->bv_len - (p - val->bv_val);
+
+ assert( normalized->bv_val );
+
+ p = q = normalized->bv_val;
+ s = NULL;
+
+ while ( p < e ) {
+ q += len;
+ if ( ASCII_SPACE( *p ) ) {
+ s = q - len;
+ len = 1;
+ *q = *p++;
+
+ /* Ignore the extra whitespace */
+ while ( ASCII_SPACE( *p ) ) {
+ p++;
+ }
+ } else {
+ len = LDAP_UTF8_COPY(q,p);
+ s=NULL;
+ p+=len;
+ }
+ }
+
+ assert( normalized->bv_val < p );
+ assert( q+len <= p );
+
+ /* cannot start with a space */
+ assert( !ASCII_SPACE(normalized->bv_val[0]) );
+
+ /*
+ * 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 ( s != NULL ) {
+ len = q - s;
+ q = s;
+ }
+
+ /* cannot end with a space */
+ assert( !ASCII_SPACE( *q ) );
+
+ q += len;
+
+ /* null terminate */
+ *q = '\0';
+
+ normalized->bv_len = q - normalized->bv_val;
+
+ return LDAP_SUCCESS;
+}
+
+/* Returns Unicode canonically normalized copy of a substring assertion
+ * Skipping attribute description */
+static SubstringsAssertion *
+UTF8SubstringsassertionNormalize(
+ SubstringsAssertion *sa,
+ unsigned casefold )
+{
+ SubstringsAssertion *nsa;
+ int i;
+
+ nsa = (SubstringsAssertion *)ch_calloc( 1, sizeof(SubstringsAssertion) );
+ if( nsa == NULL ) {
+ return NULL;
+ }
+
+ if( sa->sa_initial.bv_val != NULL ) {
+ UTF8bvnormalize( &sa->sa_initial, &nsa->sa_initial, casefold );
+ if( nsa->sa_initial.bv_val == NULL ) {
+ goto err;
+ }
+ }
+
+ if( sa->sa_any != NULL ) {
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ /* empty */
+ }
+ nsa->sa_any = (struct berval *)ch_malloc( (i + 1) * sizeof(struct berval) );
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i],
+ casefold );
+ if( nsa->sa_any[i].bv_val == NULL ) {
+ goto err;
+ }
+ }
+ nsa->sa_any[i].bv_val = NULL;
+ }
+
+ if( sa->sa_final.bv_val != NULL ) {
+ UTF8bvnormalize( &sa->sa_final, &nsa->sa_final, casefold );
+ if( nsa->sa_final.bv_val == NULL ) {
+ goto err;
+ }
+ }
+
+ return nsa;
+
+err:
+ if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val );
+ if ( nsa->sa_any )ber_bvarray_free( nsa->sa_any );
+ if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val );
+ ch_free( nsa );
+ return NULL;
+}
+
+/* Strip characters with the 8th bit set */
+static char *
+strip8bitChars(
+ char *in )
+{
+ char *p = in, *q;
+
+ if( in == NULL ) {
+ return NULL;
+ }
+ while( *p ) {
+ if( *p & 0x80 ) {
+ q = p;
+ while( *++q & 0x80 ) {
+ /* empty */
+ }
+ p = AC_MEMCPY(p, q, strlen(q) + 1);
+ } else {
+ p++;
+ }
+ }
+ return in;
+}
+
+#ifndef SLAPD_APPROX_OLDSINGLESTRING
+
+#if defined(SLAPD_APPROX_INITIALS)
+#define SLAPD_APPROX_DELIMITER "._ "
+#define SLAPD_APPROX_WORDLEN 2
+#else
+#define SLAPD_APPROX_DELIMITER " "
+#define SLAPD_APPROX_WORDLEN 1
+#endif
+
+static int
+approxMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ char *val, *nval, *assertv, **values, **words, *c;
+ int i, count, len, nextchunk=0, nextavail=0;
+ size_t avlen;
+
+ /* Yes, this is necessary */
+ nval = UTF8normalize( value, LDAP_UTF8_NOCASEFOLD );
+ if( nval == NULL ) {
+ *matchp = 1;
+ return LDAP_SUCCESS;
+ }
+ strip8bitChars( nval );
+
+ /* Yes, this is necessary */
+ assertv = UTF8normalize( ((struct berval *)assertedValue),
+ LDAP_UTF8_NOCASEFOLD );
+ if( assertv == NULL ) {
+ ch_free( nval );
+ *matchp = 1;
+ return LDAP_SUCCESS;
+ }
+ strip8bitChars( assertv );
+ avlen = strlen( assertv );
+
+ /* Isolate how many words there are */
+ for( c=nval,count=1; *c; c++ ) {
+ c = strpbrk( c, SLAPD_APPROX_DELIMITER );
+ if ( c == NULL ) break;
+ *c = '\0';
+ count++;
+ }
+
+ /* Get a phonetic copy of each word */
+ words = (char **)ch_malloc( count * sizeof(char *) );
+ values = (char **)ch_malloc( count * sizeof(char *) );
+ for( c=nval,i=0; i<count; i++,c+=strlen(c)+1 ) {
+ words[i] = c;
+ values[i] = phonetic(c);
+ }
+
+ /* Work through the asserted value's words, to see if at least some
+ of the words are there, in the same order. */
+ len = 0;
+ while ( (size_t) nextchunk < avlen ) {
+ len = strcspn( assertv + nextchunk, SLAPD_APPROX_DELIMITER);
+ if( len == 0 ) {
+ nextchunk++;
+ continue;
+ }
+#if defined(SLAPD_APPROX_INITIALS)
+ else if( len == 1 ) {
+ /* Single letter words need to at least match one word's initial */
+ for( i=nextavail; i<count; i++ )
+ if( !strncasecmp( assertv+nextchunk, words[i], 1 )) {
+ nextavail=i+1;
+ break;
+ }
+ }
+#endif
+ else {
+ /* Isolate the next word in the asserted value and phonetic it */
+ assertv[nextchunk+len] = '\0';
+ val = phonetic( assertv + nextchunk );
+
+ /* See if this phonetic chunk is in the remaining words of *value */
+ for( i=nextavail; i<count; i++ ){
+ if( !strcmp( val, values[i] ) ){
+ nextavail = i+1;
+ break;
+ }
+ }
+ ch_free( val );
+ }
+
+ /* This chunk in the asserted value was NOT within the *value. */
+ if( i >= count ) {
+ nextavail=-1;
+ break;
+ }
+
+ /* Go on to the next word in the asserted value */
+ nextchunk += len+1;
+ }
+
+ /* If some of the words were seen, call it a match */
+ if( nextavail > 0 ) {
+ *matchp = 0;
+ }
+ else {
+ *matchp = 1;
+ }
+
+ /* Cleanup allocs */
+ free( assertv );
+ for( i=0; i<count; i++ ) {
+ ch_free( values[i] );
+ }
+ ch_free( values );
+ ch_free( words );
+ ch_free( nval );
+
+ return LDAP_SUCCESS;
+}
+
+static int
+approxIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ char *val, *c;
+ int i,j, len, wordcount, keycount=0;
+ struct berval *newkeys;
+ BerVarray keys=NULL;
+
+ for( j=0; values[j].bv_val != NULL; j++ ) {
+ /* Yes, this is necessary */
+ val = UTF8normalize( &values[j], LDAP_UTF8_NOCASEFOLD );
+ strip8bitChars( val );
+
+ /* Isolate how many words there are. There will be a key for each */
+ for( wordcount=0,c=val; *c; c++) {
+ len = strcspn(c, SLAPD_APPROX_DELIMITER);
+ if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
+ c+= len;
+ if (*c == '\0') break;
+ *c = '\0';
+ }
+
+ /* Allocate/increase storage to account for new keys */
+ newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
+ * sizeof(struct berval) );
+ AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
+ if( keys ) ch_free( keys );
+ keys = newkeys;
+
+ /* Get a phonetic copy of each word */
+ for( c=val,i=0; i<wordcount; c+=len+1 ) {
+ len = strlen( c );
+ if( len < SLAPD_APPROX_WORDLEN ) continue;
+ ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
+ keycount++;
+ i++;
+ }
+
+ free( val );
+ }
+ keys[keycount].bv_val = NULL;
+ *keysp = keys;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+approxFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ char *val, *c;
+ int i, count, len;
+ BerVarray keys;
+
+ /* Yes, this is necessary */
+ val = UTF8normalize( ((struct berval *)assertValue),
+ LDAP_UTF8_NOCASEFOLD );
+ if( val == NULL ) {
+ keys = (struct berval *)ch_malloc( sizeof(struct berval) );
+ keys[0].bv_val = NULL;
+ *keysp = keys;
+ return LDAP_SUCCESS;
+ }
+ strip8bitChars( val );
+
+ /* Isolate how many words there are. There will be a key for each */
+ for( count=0,c=val; *c; c++) {
+ len = strcspn(c, SLAPD_APPROX_DELIMITER);
+ if( len >= SLAPD_APPROX_WORDLEN ) count++;
+ c+= len;
+ if (*c == '\0') break;
+ *c = '\0';
+ }
+
+ /* Allocate storage for new keys */
+ keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
+
+ /* Get a phonetic copy of each word */
+ for( c=val,i=0; i<count; c+=len+1 ) {
+ len = strlen(c);
+ if( len < SLAPD_APPROX_WORDLEN ) continue;
+ ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
+ i++;
+ }
+
+ free( val );
+
+ keys[count].bv_val = NULL;
+ *keysp = keys;
+
+ return LDAP_SUCCESS;
+}
+
+
+#else
+/* No other form of Approximate Matching is defined */
+
+static int
+approxMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ char *vapprox, *avapprox;
+ char *s, *t;
+
+ /* Yes, this is necessary */
+ s = UTF8normalize( value, UTF8_NOCASEFOLD );
+ if( s == NULL ) {
+ *matchp = 1;
+ return LDAP_SUCCESS;
+ }
+
+ /* Yes, this is necessary */
+ t = UTF8normalize( ((struct berval *)assertedValue),
+ UTF8_NOCASEFOLD );
+ if( t == NULL ) {
+ free( s );
+ *matchp = -1;
+ return LDAP_SUCCESS;
+ }
+
+ vapprox = phonetic( strip8bitChars( s ) );
+ avapprox = phonetic( strip8bitChars( t ) );
+
+ free( s );
+ free( t );
+
+ *matchp = strcmp( vapprox, avapprox );
+
+ ch_free( vapprox );
+ ch_free( avapprox );
+
+ return LDAP_SUCCESS;
+}
+
+static int
+approxIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ int i;
+ BerVarray *keys;
+ char *s;
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* empty - just count them */
+ }
+
+ /* we should have at least one value at this point */
+ assert( i > 0 );
+
+ keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) );
+
+ /* Copy each value and run it through phonetic() */
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* Yes, this is necessary */
+ s = UTF8normalize( &values[i], UTF8_NOCASEFOLD );
+
+ /* strip 8-bit chars and run through phonetic() */
+ ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] );
+ free( s );
+ }
+ keys[i].bv_val = NULL;
+
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+
+static int
+approxFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ BerVarray keys;
+ char *s;
+
+ keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 );
+
+ /* Yes, this is necessary */
+ s = UTF8normalize( ((struct berval *)assertValue),
+ UTF8_NOCASEFOLD );
+ if( s == NULL ) {
+ keys[0] = NULL;
+ } else {
+ /* strip 8-bit chars and run through phonetic() */
+ keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) );
+ free( s );
+ keys[1] = NULL;
+ }
+
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+#endif
+
+
+static int
+caseExactMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ *matchp = UTF8normcmp( value->bv_val,
+ ((struct berval *) assertedValue)->bv_val,
+ LDAP_UTF8_NOCASEFOLD );
+ return LDAP_SUCCESS;
+}
+
+static int
+caseExactIgnoreSubstringsMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int match = 0;
+ SubstringsAssertion *sub = NULL;
+ struct berval left = { 0, NULL };
+ int i;
+ ber_len_t inlen=0;
+ char *nav = NULL;
+ unsigned casefold;
+
+ casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
+ ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
+
+ if ( UTF8bvnormalize( value, &left, casefold ) == NULL ) {
+ match = 1;
+ goto done;
+ }
+ nav = left.bv_val;
+
+ sub = UTF8SubstringsassertionNormalize( assertedValue, casefold );
+ if( sub == NULL ) {
+ match = -1;
+ goto done;
+ }
+
+ /* Add up asserted input length */
+ if( sub->sa_initial.bv_val ) {
+ inlen += sub->sa_initial.bv_len;
+ }
+ if( sub->sa_any ) {
+ for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
+ inlen += sub->sa_any[i].bv_len;
+ }
+ }
+ if( sub->sa_final.bv_val ) {
+ inlen += sub->sa_final.bv_len;
+ }
+
+ if( sub->sa_initial.bv_val ) {
+ if( inlen > left.bv_len ) {
+ match = 1;
+ goto done;
+ }
+
+ match = memcmp( sub->sa_initial.bv_val, left.bv_val,
+ sub->sa_initial.bv_len );
+
+ if( match != 0 ) {
+ goto done;
+ }
+
+ left.bv_val += sub->sa_initial.bv_len;
+ left.bv_len -= sub->sa_initial.bv_len;
+ inlen -= sub->sa_initial.bv_len;
+ }
+
+ if( sub->sa_final.bv_val ) {
+ if( inlen > left.bv_len ) {
+ match = 1;
+ goto done;
+ }
+
+ match = memcmp( sub->sa_final.bv_val,
+ &left.bv_val[left.bv_len - sub->sa_final.bv_len],
+ sub->sa_final.bv_len );
+
+ if( match != 0 ) {
+ goto done;
+ }
+
+ left.bv_len -= sub->sa_final.bv_len;
+ inlen -= sub->sa_final.bv_len;
+ }
+
+ if( sub->sa_any ) {
+ for(i=0; sub->sa_any[i].bv_val; i++) {
+ ber_len_t idx;
+ char *p;
+
+retry:
+ if( inlen > left.bv_len ) {
+ /* not enough length */
+ match = 1;
+ goto done;
+ }
+
+ if( sub->sa_any[i].bv_len == 0 ) {
+ continue;
+ }
+
+ p = ber_bvchr( &left, *sub->sa_any[i].bv_val );
+ if ( p == NULL ) {
+ match = 1;
+ goto done;
+ }
+
+ idx = p - left.bv_val;
+
+ if( idx >= left.bv_len ) {
+ /* this shouldn't happen */
+ free( nav );
+ if ( sub->sa_final.bv_val )
+ ch_free( sub->sa_final.bv_val );
+ if ( sub->sa_any )
+ ber_bvarray_free( sub->sa_any );
+ if ( sub->sa_initial.bv_val )
+ ch_free( sub->sa_initial.bv_val );
+ ch_free( sub );
+ return LDAP_OTHER;
+ }
+
+ left.bv_val = p;
+ left.bv_len -= idx;
+
+ if( sub->sa_any[i].bv_len > left.bv_len ) {
+ /* not enough left */
+ match = 1;
+ goto done;
+ }
+
+ match = memcmp( left.bv_val,
+ sub->sa_any[i].bv_val,
+ sub->sa_any[i].bv_len );
+
+ if( match != 0 ) {
+ left.bv_val++;
+ left.bv_len--;
+ goto retry;
+ }
+
+ left.bv_val += sub->sa_any[i].bv_len;
+ left.bv_len -= sub->sa_any[i].bv_len;
+ inlen -= sub->sa_any[i].bv_len;
+ }
+ }
+
+done:
+ free( nav );
+ if( sub != NULL ) {
+ if ( sub->sa_final.bv_val ) free( sub->sa_final.bv_val );
+ if ( sub->sa_any ) ber_bvarray_free( sub->sa_any );
+ if ( sub->sa_initial.bv_val ) free( sub->sa_initial.bv_val );
+ ch_free( sub );
+ }
+ *matchp = match;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int caseExactIgnoreIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ int i;
+ unsigned casefold;
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* empty - just count them */
+ }
+
+ /* we should have at least one value at this point */
+ assert( i > 0 );
+
+ keys = ch_malloc( sizeof( struct berval ) * (i+1) );
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ casefold = strcmp( mr->smr_oid, caseExactMatchOID )
+ ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ struct berval value;
+ ber_str2bv( UTF8normalize( &values[i], casefold ), 0, 0,
+ &value );
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value.bv_val, value.bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ free( value.bv_val );
+
+ ber_dupbv( &keys[i], &digest );
+ }
+
+ keys[i].bv_val = NULL;
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int caseExactIgnoreFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ unsigned casefold;
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval value;
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ casefold = strcmp( mr->smr_oid, caseExactMatchOID )
+ ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
+
+ ber_str2bv( UTF8normalize( ((struct berval *) assertValue), casefold ),
+ 0, 0, &value );
+ /* This usually happens if filter contains bad UTF8 */
+ if( value.bv_val == NULL ) {
+ keys = ch_malloc( sizeof( struct berval ) );
+ keys[0].bv_val = NULL;
+ return LDAP_SUCCESS;
+ }
+
+ keys = ch_malloc( sizeof( struct berval ) * 2 );
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value.bv_val, value.bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( keys, &digest );
+ keys[1].bv_val = NULL;
+
+ free( value.bv_val );
+
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Substrings Index generation function */
+static int caseExactIgnoreSubstringsIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ unsigned casefold;
+ ber_len_t i, nkeys;
+ size_t slen, mlen;
+ BerVarray keys;
+ BerVarray nvalues;
+
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ nkeys=0;
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* empty - just count them */
+ }
+
+ /* we should have at least one value at this point */
+ assert( i > 0 );
+
+ casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
+ ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
+
+ nvalues = ch_malloc( sizeof( struct berval ) * (i+1) );
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ ber_str2bv( UTF8normalize( &values[i], casefold ),
+ 0, 0, &nvalues[i] );
+ }
+ nvalues[i].bv_val = NULL;
+ values = nvalues;
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* count number of indices to generate */
+ if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
+ continue;
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
+ ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+ } else {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_ANY ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
+ ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+ } else {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+ }
+ }
+ }
+
+ if( nkeys == 0 ) {
+ /* no keys to generate */
+ *keysp = NULL;
+ ber_bvarray_free( nvalues );
+ return LDAP_SUCCESS;
+ }
+
+ keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ nkeys=0;
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ ber_len_t j,max;
+
+ if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
+
+ if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
+ ( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
+ {
+ char pre = SLAP_INDEX_SUBSTR_PREFIX;
+ max = values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
+
+ for( j=0; j<max; j++ ) {
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &values[i].bv_val[j],
+ SLAP_INDEX_SUBSTR_MAXLEN );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+ }
+
+ max = SLAP_INDEX_SUBSTR_MAXLEN < values[i].bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : values[i].bv_len;
+
+ for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
+ char pre;
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
+ pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ values[i].bv_val, j );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
+ pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &values[i].bv_val[values[i].bv_len-j], j );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ }
+
+ }
+
+ if( nkeys > 0 ) {
+ keys[nkeys].bv_val = NULL;
+ *keysp = keys;
+ } else {
+ ch_free( keys );
+ *keysp = NULL;
+ }
+
+ ber_bvarray_free( nvalues );
+
+ return LDAP_SUCCESS;
+}
+
+static int caseExactIgnoreSubstringsFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ SubstringsAssertion *sa;
+ char pre;
+ unsigned casefold;
+ ber_len_t nkeys = 0;
+ size_t slen, mlen, klen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval *value;
+ struct berval digest;
+
+ casefold = strcmp( mr->smr_oid, caseExactSubstringsMatchOID )
+ ? LDAP_UTF8_CASEFOLD : LDAP_UTF8_NOCASEFOLD;
+
+ sa = UTF8SubstringsassertionNormalize( assertValue, casefold );
+ if( sa == NULL ) {
+ *keysp = NULL;
+ return LDAP_SUCCESS;
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
+ sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ nkeys++;
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
+ ber_len_t i;
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ /* don't bother accounting for stepping */
+ nkeys += sa->sa_any[i].bv_len -
+ ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
+ }
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
+ sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ nkeys++;
+ }
+
+ if( nkeys == 0 ) {
+ if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
+ if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
+ if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
+ ch_free( sa );
+ *keysp = NULL;
+ return LDAP_SUCCESS;
+ }
+
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
+ nkeys = 0;
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
+ sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+ value = &sa->sa_initial;
+
+ klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value->bv_val, klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
+ ber_len_t i, j;
+ pre = SLAP_INDEX_SUBSTR_PREFIX;
+ klen = SLAP_INDEX_SUBSTR_MAXLEN;
+
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
+ continue;
+ }
+
+ value = &sa->sa_any[i];
+
+ for(j=0;
+ j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
+ j += SLAP_INDEX_SUBSTR_STEP )
+ {
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value->bv_val[j], klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
+ sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+ value = &sa->sa_final;
+
+ klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value->bv_val[value->bv_len-klen], klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( nkeys > 0 ) {
+ keys[nkeys].bv_val = NULL;
+ *keysp = keys;
+ } else {
+ ch_free( keys );
+ *keysp = NULL;
+ }
+ if ( sa->sa_final.bv_val ) free( sa->sa_final.bv_val );
+ if ( sa->sa_any ) ber_bvarray_free( sa->sa_any );
+ if ( sa->sa_initial.bv_val ) free( sa->sa_initial.bv_val );
+ ch_free( sa );
+
+ return LDAP_SUCCESS;
+}
+
+static int
+caseIgnoreMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ *matchp = UTF8normcmp( value->bv_val,
+ ((struct berval *) assertedValue)->bv_val,
+ LDAP_UTF8_CASEFOLD );
+ return LDAP_SUCCESS;
+}
+
+static int
+oidValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ ber_len_t i;
+
+ if( val->bv_len == 0 ) {
+ /* disallow empty strings */
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if( OID_LEADCHAR(val->bv_val[0]) ) {
+ int dot = 0;
+ for(i=1; i < val->bv_len; i++) {
+ if( OID_SEPARATOR( val->bv_val[i] ) ) {
+ if( dot++ ) return 1;
+ } else if ( OID_CHAR( val->bv_val[i] ) ) {
+ dot = 0;
+ } else {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return !dot ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
+
+ } else if( DESC_LEADCHAR(val->bv_val[0]) ) {
+ for(i=1; i < val->bv_len; i++) {
+ if( !DESC_CHAR(val->bv_val[i] ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+ }
+
+ return LDAP_INVALID_SYNTAX;
+}
+
+static int
+integerMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ char *v, *av;
+ int vsign=0, avsign=0;
+ struct berval *asserted;
+ ber_len_t vlen, avlen;
+
+
+ /* Start off pessimistic */
+ *matchp = 1;
+
+ /* Skip past leading spaces/zeros, and get the sign of the *value number */
+ v = value->bv_val;
+ vlen = value->bv_len;
+ while( vlen ) {
+ if( ASCII_SPACE(*v) || ( *v == '0' )) {
+ /* empty -- skip spaces */
+ }
+ else if ( *v == '+' ) {
+ vsign = 1;
+ }
+ else if ( *v == '-' ) {
+ vsign = -1;
+ }
+ else if ( ASCII_DIGIT(*v) ) {
+ if ( vsign == 0 ) vsign = 1;
+ vsign *= 2;
+ break;
+ }
+ v++;
+ vlen--;
+ }
+
+ /* Skip past leading spaces/zeros, and get the sign of the *assertedValue
+ number */
+ asserted = (struct berval *) assertedValue;
+ av = asserted->bv_val;
+ avlen = asserted->bv_len;
+ while( avlen ) {
+ if( ASCII_SPACE(*av) || ( *av == '0' )) {
+ /* empty -- skip spaces */
+ }
+ else if ( *av == '+' ) {
+ avsign = 1;
+ }
+ else if ( *av == '-' ) {
+ avsign = -1;
+ }
+ else if ( ASCII_DIGIT(*av) ) {
+ if ( avsign == 0 ) avsign = 1;
+ avsign *= 2;
+ break;
+ }
+ av++;
+ avlen--;
+ }
+
+ /* The two ?sign vars are now one of :
+ -2 negative non-zero number
+ -1 -0 \
+ 0 0 collapse these three to 0
+ +1 +0 /
+ +2 positive non-zero number
+ */
+ if ( abs( vsign ) == 1 ) vsign = 0;
+ if ( abs( avsign ) == 1 ) avsign = 0;
+
+ if( vsign != avsign ) return LDAP_SUCCESS;
+
+ /* Check the significant digits */
+ while( vlen && avlen ) {
+ if( *v != *av ) break;
+ v++;
+ vlen--;
+ av++;
+ avlen--;
+ }
+
+ /* If all digits compared equal, the numbers are equal */
+ if(( vlen == 0 ) && ( avlen == 0 )) {
+ *matchp = 0;
+ }
+ return LDAP_SUCCESS;
+}
+
+static int
+integerValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ ber_len_t i;
+
+ if( !val->bv_len ) return LDAP_INVALID_SYNTAX;
+
+ if(( val->bv_val[0] == '+' ) || ( val->bv_val[0] == '-' )) {
+ if( val->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
+ } else if( !ASCII_DIGIT(val->bv_val[0]) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for( i=1; i < val->bv_len; i++ ) {
+ if( !ASCII_DIGIT(val->bv_val[i]) ) return LDAP_INVALID_SYNTAX;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+integerNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ char *p;
+ int negative=0;
+ ber_len_t len;
+
+
+ p = val->bv_val;
+ len = val->bv_len;
+
+ /* Ignore leading spaces */
+ while ( len && ( *p == ' ' )) {
+ p++;
+ len--;
+ }
+
+ /* save sign */
+ if( len ) {
+ negative = ( *p == '-' );
+ if(( *p == '-' ) || ( *p == '+' )) {
+ p++;
+ len--;
+ }
+ }
+
+ /* Ignore leading zeros */
+ while ( len && ( *p == '0' )) {
+ p++;
+ len--;
+ }
+
+ /* If there are no non-zero digits left, the number is zero, otherwise
+ allocate space for the number and copy it into the buffer */
+ if( len == 0 ) {
+ normalized->bv_val = ch_strdup("0");
+ normalized->bv_len = 1;
+ }
+ else {
+ normalized->bv_len = len+negative;
+ normalized->bv_val = ch_malloc( normalized->bv_len );
+ if( negative ) {
+ normalized->bv_val[0] = '-';
+ }
+ AC_MEMCPY( normalized->bv_val + negative, p, len );
+ }
+
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int integerIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ int i;
+ BerVarray keys;
+
+ /* we should have at least one value at this point */
+ assert( values != NULL && values[0].bv_val != NULL );
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* empty -- just count them */
+ }
+
+ keys = ch_malloc( sizeof( struct berval ) * (i+1) );
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ integerNormalize( syntax, &values[i], &keys[i] );
+ }
+
+ keys[i].bv_val = NULL;
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int integerFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ BerVarray keys;
+
+ keys = ch_malloc( sizeof( struct berval ) * 2 );
+ integerNormalize( syntax, assertValue, &keys[0] );
+ keys[1].bv_val = NULL;
+ *keysp = keys;
+
+ return LDAP_SUCCESS;
+}
+
+
+static int
+countryStringValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
+
+ if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+printableStringValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ ber_len_t i;
+
+ for(i=0; i < val->bv_len; i++) {
+ if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+printablesStringValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ ber_len_t i;
+
+ for(i=0; i < val->bv_len; i++) {
+ if( !SLAP_PRINTABLES(val->bv_val[i]) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+IA5StringValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ ber_len_t i;
+
+ for(i=0; i < val->bv_len; i++) {
+ if( !LDAP_ASCII(val->bv_val[i]) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+IA5StringNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ char *p, *q;
+
+ p = val->bv_val;
+
+ /* Ignore initial whitespace */
+ while ( ASCII_SPACE( *p ) ) {
+ p++;
+ }
+
+ normalized->bv_val = ch_strdup( p );
+ p = q = normalized->bv_val;
+
+ while ( *p ) {
+ if ( ASCII_SPACE( *p ) ) {
+ *q++ = *p++;
+
+ /* Ignore the extra whitespace */
+ while ( ASCII_SPACE( *p ) ) {
+ p++;
+ }
+ } else {
+ *q++ = *p++;
+ }
+ }
+
+ assert( normalized->bv_val <= p );
+ assert( 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 ( ASCII_SPACE( q[-1] ) ) {
+ --q;
+ }
+
+ /* null terminate */
+ *q = '\0';
+
+ normalized->bv_len = q - normalized->bv_val;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+caseExactIA5Match(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
+
+ if( match == 0 ) {
+ match = strncmp( value->bv_val,
+ ((struct berval *) assertedValue)->bv_val,
+ value->bv_len );
+ }
+
+ *matchp = match;
+ return LDAP_SUCCESS;
+}
+
+static int
+caseExactIA5SubstringsMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int match = 0;
+ SubstringsAssertion *sub = assertedValue;
+ struct berval left = *value;
+ int i;
+ ber_len_t inlen=0;
+
+ /* Add up asserted input length */
+ if( sub->sa_initial.bv_val ) {
+ inlen += sub->sa_initial.bv_len;
+ }
+ if( sub->sa_any ) {
+ for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
+ inlen += sub->sa_any[i].bv_len;
+ }
+ }
+ if( sub->sa_final.bv_val ) {
+ inlen += sub->sa_final.bv_len;
+ }
+
+ if( sub->sa_initial.bv_val ) {
+ if( inlen > left.bv_len ) {
+ match = 1;
+ goto done;
+ }
+
+ match = strncmp( sub->sa_initial.bv_val, left.bv_val,
+ sub->sa_initial.bv_len );
+
+ if( match != 0 ) {
+ goto done;
+ }
+
+ left.bv_val += sub->sa_initial.bv_len;
+ left.bv_len -= sub->sa_initial.bv_len;
+ inlen -= sub->sa_initial.bv_len;
+ }
+
+ if( sub->sa_final.bv_val ) {
+ if( inlen > left.bv_len ) {
+ match = 1;
+ goto done;
+ }
+
+ match = strncmp( sub->sa_final.bv_val,
+ &left.bv_val[left.bv_len - sub->sa_final.bv_len],
+ sub->sa_final.bv_len );
+
+ if( match != 0 ) {
+ goto done;
+ }
+
+ left.bv_len -= sub->sa_final.bv_len;
+ inlen -= sub->sa_final.bv_len;
+ }
+
+ if( sub->sa_any ) {
+ for(i=0; sub->sa_any[i].bv_val; i++) {
+ ber_len_t idx;
+ char *p;
+
+retry:
+ if( inlen > left.bv_len ) {
+ /* not enough length */
+ match = 1;
+ goto done;
+ }
+
+ if( sub->sa_any[i].bv_len == 0 ) {
+ continue;
+ }
+
+ p = strchr( left.bv_val, *sub->sa_any[i].bv_val );
+
+ if( p == NULL ) {
+ match = 1;
+ goto done;
+ }
+
+ idx = p - left.bv_val;
+
+ if( idx >= left.bv_len ) {
+ /* this shouldn't happen */
+ return LDAP_OTHER;
+ }
+
+ left.bv_val = p;
+ left.bv_len -= idx;
+
+ if( sub->sa_any[i].bv_len > left.bv_len ) {
+ /* not enough left */
+ match = 1;
+ goto done;
+ }
+
+ match = strncmp( left.bv_val,
+ sub->sa_any[i].bv_val,
+ sub->sa_any[i].bv_len );
+
+ if( match != 0 ) {
+ left.bv_val++;
+ left.bv_len--;
+ goto retry;
+ }
+
+ left.bv_val += sub->sa_any[i].bv_len;
+ left.bv_len -= sub->sa_any[i].bv_len;
+ inlen -= sub->sa_any[i].bv_len;
+ }
+ }
+
+done:
+ *matchp = match;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int caseExactIA5Indexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ int i;
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* empty - just count them */
+ }
+
+ /* we should have at least one value at this point */
+ assert( i > 0 );
+
+ keys = ch_malloc( sizeof( struct berval ) * (i+1) );
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ struct berval *value = &values[i];
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value->bv_val, value->bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[i], &digest );
+ }
+
+ keys[i].bv_val = NULL;
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int caseExactIA5Filter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval *value;
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ value = (struct berval *) assertValue;
+
+ keys = ch_malloc( sizeof( struct berval ) * 2 );
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value->bv_val, value->bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[0], &digest );
+ keys[1].bv_val = NULL;
+
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Substrings Index generation function */
+static int caseExactIA5SubstringsIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ ber_len_t i, nkeys;
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ /* we should have at least one value at this point */
+ assert( values != NULL && values[0].bv_val != NULL );
+
+ nkeys=0;
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* count number of indices to generate */
+ if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
+ continue;
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
+ ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+ } else {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_ANY ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
+ ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+ } else {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+ }
+ }
+ }
+
+ if( nkeys == 0 ) {
+ /* no keys to generate */
+ *keysp = NULL;
+ return LDAP_SUCCESS;
+ }
+
+ keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ nkeys=0;
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ ber_len_t j,max;
+ struct berval *value;
+
+ value = &values[i];
+ if( value->bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
+
+ if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
+ ( value->bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
+ {
+ char pre = SLAP_INDEX_SUBSTR_PREFIX;
+ max = value->bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
+
+ for( j=0; j<max; j++ ) {
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value->bv_val[j],
+ SLAP_INDEX_SUBSTR_MAXLEN );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+ }
+
+ max = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+ for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
+ char pre;
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
+ pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value->bv_val, j );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
+ pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value->bv_val[value->bv_len-j], j );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ }
+ }
+
+ if( nkeys > 0 ) {
+ keys[nkeys].bv_val = NULL;
+ *keysp = keys;
+ } else {
+ ch_free( keys );
+ *keysp = NULL;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int caseExactIA5SubstringsFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ SubstringsAssertion *sa = assertValue;
+ char pre;
+ ber_len_t nkeys = 0;
+ size_t slen, mlen, klen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval *value;
+ struct berval digest;
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
+ sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ nkeys++;
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
+ ber_len_t i;
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ /* don't bother accounting for stepping */
+ nkeys += sa->sa_any[i].bv_len -
+ ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
+ }
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
+ sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ nkeys++;
+ }
+
+ if( nkeys == 0 ) {
+ *keysp = NULL;
+ return LDAP_SUCCESS;
+ }
+
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
+ nkeys = 0;
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL && sa->sa_initial.bv_val != NULL &&
+ sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+ value = &sa->sa_initial;
+
+ klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value->bv_val, klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
+ ber_len_t i, j;
+ pre = SLAP_INDEX_SUBSTR_PREFIX;
+ klen = SLAP_INDEX_SUBSTR_MAXLEN;
+
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
+ continue;
+ }
+
+ value = &sa->sa_any[i];
+
+ for(j=0;
+ j <= value->bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
+ j += SLAP_INDEX_SUBSTR_STEP )
+ {
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value->bv_val[j], klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL && sa->sa_final.bv_val != NULL &&
+ sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+ value = &sa->sa_final;
+
+ klen = SLAP_INDEX_SUBSTR_MAXLEN < value->bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value->bv_len;
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value->bv_val[value->bv_len-klen], klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( nkeys > 0 ) {
+ keys[nkeys].bv_val = NULL;
+ *keysp = keys;
+ } else {
+ ch_free( keys );
+ *keysp = NULL;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+caseIgnoreIA5Match(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int match = value->bv_len - ((struct berval *) assertedValue)->bv_len;
+
+ if( match == 0 && value->bv_len ) {
+ match = strncasecmp( value->bv_val,
+ ((struct berval *) assertedValue)->bv_val,
+ value->bv_len );
+ }
+
+ *matchp = match;
+ return LDAP_SUCCESS;
+}
+
+static int
+caseIgnoreIA5SubstringsMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int match = 0;
+ SubstringsAssertion *sub = assertedValue;
+ struct berval left = *value;
+ int i;
+ ber_len_t inlen=0;
+
+ /* Add up asserted input length */
+ if( sub->sa_initial.bv_val ) {
+ inlen += sub->sa_initial.bv_len;
+ }
+ if( sub->sa_any ) {
+ for(i=0; sub->sa_any[i].bv_val != NULL; i++) {
+ inlen += sub->sa_any[i].bv_len;
+ }
+ }
+ if( sub->sa_final.bv_val ) {
+ inlen += sub->sa_final.bv_len;
+ }
+
+ if( sub->sa_initial.bv_val ) {
+ if( inlen > left.bv_len ) {
+ match = 1;
+ goto done;
+ }
+
+ match = strncasecmp( sub->sa_initial.bv_val, left.bv_val,
+ sub->sa_initial.bv_len );
+
+ if( match != 0 ) {
+ goto done;
+ }
+
+ left.bv_val += sub->sa_initial.bv_len;
+ left.bv_len -= sub->sa_initial.bv_len;
+ inlen -= sub->sa_initial.bv_len;
+ }
+
+ if( sub->sa_final.bv_val ) {
+ if( inlen > left.bv_len ) {
+ match = 1;
+ goto done;
+ }
+
+ match = strncasecmp( sub->sa_final.bv_val,
+ &left.bv_val[left.bv_len - sub->sa_final.bv_len],
+ sub->sa_final.bv_len );
+
+ if( match != 0 ) {
+ goto done;
+ }
+
+ left.bv_len -= sub->sa_final.bv_len;
+ inlen -= sub->sa_final.bv_len;
+ }
+
+ if( sub->sa_any ) {
+ for(i=0; sub->sa_any[i].bv_val; i++) {
+ ber_len_t idx;
+ char *p;
+
+retry:
+ if( inlen > left.bv_len ) {
+ /* not enough length */
+ match = 1;
+ goto done;
+ }
+
+ if( sub->sa_any[i].bv_len == 0 ) {
+ continue;
+ }
+
+ p = bvcasechr( &left, *sub->sa_any[i].bv_val, &idx );
+
+ if( p == NULL ) {
+ match = 1;
+ goto done;
+ }
+
+ assert( idx < left.bv_len );
+ if( idx >= left.bv_len ) {
+ /* this shouldn't happen */
+ return LDAP_OTHER;
+ }
+
+ left.bv_val = p;
+ left.bv_len -= idx;
+
+ if( sub->sa_any[i].bv_len > left.bv_len ) {
+ /* not enough left */
+ match = 1;
+ goto done;
+ }
+
+ match = strncasecmp( left.bv_val,
+ sub->sa_any[i].bv_val,
+ sub->sa_any[i].bv_len );
+
+ if( match != 0 ) {
+ left.bv_val++;
+ left.bv_len--;
+
+ goto retry;
+ }
+
+ left.bv_val += sub->sa_any[i].bv_len;
+ left.bv_len -= sub->sa_any[i].bv_len;
+ inlen -= sub->sa_any[i].bv_len;
+ }
+ }
+
+done:
+ *matchp = match;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int caseIgnoreIA5Indexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ int i;
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ /* we should have at least one value at this point */
+ assert( values != NULL && values[0].bv_val != NULL );
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* just count them */
+ }
+
+ keys = ch_malloc( sizeof( struct berval ) * (i+1) );
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ struct berval value;
+ ber_dupbv( &value, &values[i] );
+ ldap_pvt_str2upper( value.bv_val );
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value.bv_val, value.bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ free( value.bv_val );
+
+ ber_dupbv( &keys[i], &digest );
+ }
+
+ keys[i].bv_val = NULL;
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+static int caseIgnoreIA5Filter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval value;
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ ber_dupbv( &value, (struct berval *) assertValue );
+ ldap_pvt_str2upper( value.bv_val );
+
+ keys = ch_malloc( sizeof( struct berval ) * 2 );
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value.bv_val, value.bv_len );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[0], &digest );
+ keys[1].bv_val = NULL;
+
+ free( value.bv_val );
+
+ *keysp = keys;
+
+ return LDAP_SUCCESS;
+}
+
+/* Substrings Index generation function */
+static int caseIgnoreIA5SubstringsIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ ber_len_t i, nkeys;
+ size_t slen, mlen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval digest;
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ /* we should have at least one value at this point */
+ assert( values != NULL && values[0].bv_val != NULL );
+
+ nkeys=0;
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* count number of indices to generate */
+ if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) {
+ continue;
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
+ ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+ } else {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_ANY ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
+ }
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
+ if( values[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ nkeys += SLAP_INDEX_SUBSTR_MAXLEN -
+ ( SLAP_INDEX_SUBSTR_MINLEN - 1);
+ } else {
+ nkeys += values[i].bv_len - ( SLAP_INDEX_SUBSTR_MINLEN - 1 );
+ }
+ }
+ }
+
+ if( nkeys == 0 ) {
+ /* no keys to generate */
+ *keysp = NULL;
+ return LDAP_SUCCESS;
+ }
+
+ keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ nkeys=0;
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ int j,max;
+ struct berval value;
+
+ if( values[i].bv_len < SLAP_INDEX_SUBSTR_MINLEN ) continue;
+
+ ber_dupbv( &value, &values[i] );
+ ldap_pvt_str2upper( value.bv_val );
+
+ if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
+ ( value.bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) )
+ {
+ char pre = SLAP_INDEX_SUBSTR_PREFIX;
+ max = value.bv_len - ( SLAP_INDEX_SUBSTR_MAXLEN - 1);
+
+ for( j=0; j<max; j++ ) {
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value.bv_val[j],
+ SLAP_INDEX_SUBSTR_MAXLEN );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+ }
+
+ max = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
+
+ for( j=SLAP_INDEX_SUBSTR_MINLEN; j<=max; j++ ) {
+ char pre;
+
+ if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
+ pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value.bv_val, j );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
+ pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value.bv_val[value.bv_len-j], j );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ }
+
+ free( value.bv_val );
+ }
+
+ if( nkeys > 0 ) {
+ keys[nkeys].bv_val = NULL;
+ *keysp = keys;
+ } else {
+ ch_free( keys );
+ *keysp = NULL;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int caseIgnoreIA5SubstringsFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ SubstringsAssertion *sa = assertValue;
+ char pre;
+ ber_len_t nkeys = 0;
+ size_t slen, mlen, klen;
+ BerVarray keys;
+ HASH_CONTEXT HASHcontext;
+ unsigned char HASHdigest[HASH_BYTES];
+ struct berval value;
+ struct berval digest;
+
+ if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
+ sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ nkeys++;
+ }
+
+ if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
+ ber_len_t i;
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ if( sa->sa_any[i].bv_len >= SLAP_INDEX_SUBSTR_MAXLEN ) {
+ /* don't bother accounting for stepping */
+ nkeys += sa->sa_any[i].bv_len -
+ ( SLAP_INDEX_SUBSTR_MAXLEN - 1 );
+ }
+ }
+ }
+
+ if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
+ sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ nkeys++;
+ }
+
+ if( nkeys == 0 ) {
+ *keysp = NULL;
+ return LDAP_SUCCESS;
+ }
+
+ digest.bv_val = HASHdigest;
+ digest.bv_len = sizeof(HASHdigest);
+
+ slen = syntax->ssyn_oidlen;
+ mlen = mr->smr_oidlen;
+
+ keys = ch_malloc( sizeof( struct berval ) * (nkeys+1) );
+ nkeys = 0;
+
+ if((flags & SLAP_INDEX_SUBSTR_INITIAL) && sa->sa_initial.bv_val != NULL &&
+ sa->sa_initial.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
+ ber_dupbv( &value, &sa->sa_initial );
+ ldap_pvt_str2upper( value.bv_val );
+
+ klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ value.bv_val, klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ free( value.bv_val );
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if((flags & SLAP_INDEX_SUBSTR_ANY) && sa->sa_any != NULL ) {
+ ber_len_t i, j;
+ pre = SLAP_INDEX_SUBSTR_PREFIX;
+ klen = SLAP_INDEX_SUBSTR_MAXLEN;
+
+ for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) {
+ if( sa->sa_any[i].bv_len < SLAP_INDEX_SUBSTR_MAXLEN ) {
+ continue;
+ }
+
+ ber_dupbv( &value, &sa->sa_any[i] );
+ ldap_pvt_str2upper( value.bv_val );
+
+ for(j=0;
+ j <= value.bv_len - SLAP_INDEX_SUBSTR_MAXLEN;
+ j += SLAP_INDEX_SUBSTR_STEP )
+ {
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value.bv_val[j], klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ free( value.bv_val );
+ }
+ }
+
+ if((flags & SLAP_INDEX_SUBSTR_FINAL) && sa->sa_final.bv_val != NULL &&
+ sa->sa_final.bv_len >= SLAP_INDEX_SUBSTR_MINLEN )
+ {
+ pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
+ ber_dupbv( &value, &sa->sa_final );
+ ldap_pvt_str2upper( value.bv_val );
+
+ klen = SLAP_INDEX_SUBSTR_MAXLEN < value.bv_len
+ ? SLAP_INDEX_SUBSTR_MAXLEN : value.bv_len;
+
+ HASH_Init( &HASHcontext );
+ if( prefix != NULL && prefix->bv_len > 0 ) {
+ HASH_Update( &HASHcontext,
+ prefix->bv_val, prefix->bv_len );
+ }
+ HASH_Update( &HASHcontext,
+ &pre, sizeof( pre ) );
+ HASH_Update( &HASHcontext,
+ syntax->ssyn_oid, slen );
+ HASH_Update( &HASHcontext,
+ mr->smr_oid, mlen );
+ HASH_Update( &HASHcontext,
+ &value.bv_val[value.bv_len-klen], klen );
+ HASH_Final( HASHdigest, &HASHcontext );
+
+ free( value.bv_val );
+ ber_dupbv( &keys[nkeys++], &digest );
+ }
+
+ if( nkeys > 0 ) {
+ keys[nkeys].bv_val = NULL;
+ *keysp = keys;
+ } else {
+ ch_free( keys );
+ *keysp = NULL;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+numericStringValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ ber_len_t i;
+
+ for(i=0; i < in->bv_len; i++) {
+ if( !SLAP_NUMERIC(in->bv_val[i]) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+numericStringNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ /* removal all spaces */
+ char *p, *q;
+
+ normalized->bv_val = ch_malloc( val->bv_len + 1 );
+
+ p = val->bv_val;
+ q = normalized->bv_val;
+
+ while ( *p ) {
+ if ( ASCII_SPACE( *p ) ) {
+ /* Ignore whitespace */
+ p++;
+ } else {
+ *q++ = *p++;
+ }
+ }
+
+ /* we should have copied no more then is in val */
+ assert( (q - normalized->bv_val) <= (p - val->bv_val) );
+
+ /* null terminate */
+ *q = '\0';
+
+ normalized->bv_len = q - normalized->bv_val;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+objectIdentifierFirstComponentMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int rc = LDAP_SUCCESS;
+ int match;
+ struct berval *asserted = (struct berval *) assertedValue;
+ ber_len_t i;
+ struct berval oid;
+
+ if( value->bv_len == 0 || value->bv_val[0] != '(' /*')'*/ ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* trim leading white space */
+ for( i=1; ASCII_SPACE(value->bv_val[i]) && i < value->bv_len; i++ ) {
+ /* empty */
+ }
+
+ /* grab next word */
+ oid.bv_val = &value->bv_val[i];
+ oid.bv_len = value->bv_len - i;
+ for( i=1; ASCII_SPACE(value->bv_val[i]) && i < oid.bv_len; i++ ) {
+ /* empty */
+ }
+ oid.bv_len = i;
+
+ /* insert attributeTypes, objectclass check here */
+ if( OID_LEADCHAR(asserted->bv_val[0]) ) {
+ rc = objectIdentifierMatch( &match, flags, syntax, mr, &oid, asserted );
+
+ } else {
+ if ( !strcmp( syntax->ssyn_oid, SLAP_SYNTAX_MATCHINGRULES_OID ) ) {
+ MatchingRule *asserted_mr = mr_bvfind( asserted );
+ MatchingRule *stored_mr = mr_bvfind( &oid );
+
+ if( asserted_mr == NULL ) {
+ rc = SLAPD_COMPARE_UNDEFINED;
+ } else {
+ match = asserted_mr != stored_mr;
+ }
+
+ } else if ( !strcmp( syntax->ssyn_oid,
+ SLAP_SYNTAX_ATTRIBUTETYPES_OID ) )
+ {
+ AttributeType *asserted_at = at_bvfind( asserted );
+ AttributeType *stored_at = at_bvfind( &oid );
+
+ if( asserted_at == NULL ) {
+ rc = SLAPD_COMPARE_UNDEFINED;
+ } else {
+ match = asserted_at != stored_at;
+ }
+
+ } else if ( !strcmp( syntax->ssyn_oid,
+ SLAP_SYNTAX_OBJECTCLASSES_OID ) )
+ {
+ ObjectClass *asserted_oc = oc_bvfind( asserted );
+ ObjectClass *stored_oc = oc_bvfind( &oid );
+
+ if( asserted_oc == NULL ) {
+ rc = SLAPD_COMPARE_UNDEFINED;
+ } else {
+ match = asserted_oc != stored_oc;
+ }
+ }
+ }
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "objectIdentifierFirstComponentMatch: %d\n %s\n %s\n",
+ match, value->bv_val, asserted->bv_val ));
+#else
+ Debug( LDAP_DEBUG_ARGS, "objectIdentifierFirstComponentMatch "
+ "%d\n\t\"%s\"\n\t\"%s\"\n",
+ match, value->bv_val, asserted->bv_val );
+#endif
+
+
+ if( rc == LDAP_SUCCESS ) *matchp = match;
+ return rc;
+}
+
+static int
+integerBitAndMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ long lValue, lAssertedValue;
+
+ /* safe to assume integers are NUL terminated? */
+ lValue = strtoul(value->bv_val, NULL, 10);
+ if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
+ return LDAP_CONSTRAINT_VIOLATION;
+
+ lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
+ if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
+ return LDAP_CONSTRAINT_VIOLATION;
+
+ *matchp = (lValue & lAssertedValue);
+ return LDAP_SUCCESS;
+}
+
+static int
+integerBitOrMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ long lValue, lAssertedValue;
+
+ /* safe to assume integers are NUL terminated? */
+ lValue = strtoul(value->bv_val, NULL, 10);
+ if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE )
+ return LDAP_CONSTRAINT_VIOLATION;
+
+ lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10);
+ if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) && errno == ERANGE )
+ return LDAP_CONSTRAINT_VIOLATION;
+
+ *matchp = (lValue | lAssertedValue);
+ return LDAP_SUCCESS;
+}
+
+#ifdef HAVE_TLS
+#include <openssl/x509.h>
+#include <openssl/err.h>
+char digit[] = "0123456789";
+
+/*
+ * Next function returns a string representation of a ASN1_INTEGER.
+ * It works for unlimited lengths.
+ */
+
+static struct berval *
+asn1_integer2str(ASN1_INTEGER *a)
+{
+ char buf[256];
+ char *p;
+
+ /* We work backwards, make it fill from the end of buf */
+ p = buf + sizeof(buf) - 1;
+ *p = '\0';
+
+ if ( a == NULL || a->length == 0 ) {
+ *--p = '0';
+ } else {
+ int i;
+ int n = a->length;
+ int base = 0;
+ unsigned int *copy;
+
+ /* We want to preserve the original */
+ copy = ch_malloc(n*sizeof(unsigned int));
+ for (i = 0; i<n; i++) {
+ copy[i] = a->data[i];
+ }
+
+ /*
+ * base indicates the index of the most significant
+ * byte that might be nonzero. When it goes off the
+ * end, we now there is nothing left to do.
+ */
+ while (base < n) {
+ unsigned int carry;
+
+ carry = 0;
+ for (i = base; i<n; i++ ) {
+ copy[i] += carry*256;
+ carry = copy[i] % 10;
+ copy[i] /= 10;
+ }
+ if (p <= buf+1) {
+ /*
+ * Way too large, we need to leave
+ * room for sign if negative
+ */
+ free(copy);
+ return NULL;
+ }
+ *--p = digit[carry];
+ if (copy[base] == 0)
+ base++;
+ }
+ free(copy);
+ }
+
+ if ( a->type == V_ASN1_NEG_INTEGER ) {
+ *--p = '-';
+ }
+
+ return ber_bvstrdup(p);
+}
+
+/* Get a DN in RFC2253 format from a X509_NAME internal struct */
+static struct berval *
+dn_openssl2ldap(X509_NAME *name)
+{
+ char issuer_dn[1024];
+ BIO *bio;
+
+ bio = BIO_new(BIO_s_mem());
+ if ( !bio ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "dn_openssl2ldap: error creating BIO_s_mem: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "dn_openssl2ldap: "
+ "error creating BIO: %s\n",
+ ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
+ return NULL;
+ }
+ X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
+
+ BIO_gets(bio, issuer_dn, 1024);
+
+ BIO_free(bio);
+ return ber_bvstrdup(issuer_dn);
+}
+
+/*
+ * Given a certificate in DER format, extract the corresponding
+ * assertion value for certificateExactMatch
+ */
+static int
+certificateExactConvert(
+ struct berval * in,
+ struct berval * out )
+{
+ X509 *xcert;
+ unsigned char *p = in->bv_val;
+ struct berval *serial;
+ struct berval *issuer_dn;
+ struct berval *bv_tmp;
+
+ xcert = d2i_X509(NULL, &p, in->bv_len);
+ if ( !xcert ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactConvert: error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
+ "error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ serial = asn1_integer2str(xcert->cert_info->serialNumber);
+ if ( !serial ) {
+ X509_free(xcert);
+ return LDAP_INVALID_SYNTAX;
+ }
+ issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
+ if ( !issuer_dn ) {
+ X509_free(xcert);
+ ber_bvfree(serial);
+ return LDAP_INVALID_SYNTAX;
+ }
+ /* Actually, dn_openssl2ldap returns in a normalized format, but
+ it is different from our normalized format */
+ bv_tmp = issuer_dn;
+ if ( dnNormalize(NULL, bv_tmp, &issuer_dn) != LDAP_SUCCESS ) {
+ X509_free(xcert);
+ ber_bvfree(serial);
+ ber_bvfree(bv_tmp);
+ return LDAP_INVALID_SYNTAX;
+ }
+ ber_bvfree(bv_tmp);
+
+ X509_free(xcert);
+
+ out->bv_len = serial->bv_len + issuer_dn->bv_len + sizeof(" $ ");
+ out->bv_val = ch_malloc(out->bv_len);
+ p = out->bv_val;
+ AC_MEMCPY(p, serial->bv_val, serial->bv_len);
+ p += serial->bv_len;
+ AC_MEMCPY(p, " $ ", sizeof(" $ ")-1);
+ p += 3;
+ AC_MEMCPY(p, issuer_dn->bv_val, issuer_dn->bv_len);
+ p += issuer_dn->bv_len;
+ *p++ = '\0';
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactConvert: \n %s\n",
+ out->bv_val));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactConvert "
+ "\n\t\"%s\"\n",
+ out->bv_val, NULL, NULL );
+#endif
+
+ ber_bvfree(serial);
+ ber_bvfree(issuer_dn);
+
+ return LDAP_SUCCESS;
+}
+
+static int
+serial_and_issuer_parse(
+ struct berval *assertion,
+ struct berval **serial,
+ struct berval **issuer_dn
+)
+{
+ char *begin;
+ char *end;
+ char *p;
+ struct berval bv;
+
+ begin = assertion->bv_val;
+ end = assertion->bv_val+assertion->bv_len-1;
+ for (p=begin; p<=end && *p != '$'; p++)
+ ;
+ if ( p > end )
+ return LDAP_INVALID_SYNTAX;
+
+ /* p now points at the $ sign, now use begin and end to delimit the
+ serial number */
+ while (ASCII_SPACE(*begin))
+ begin++;
+ end = p-1;
+ while (ASCII_SPACE(*end))
+ end--;
+
+ bv.bv_len = end-begin+1;
+ bv.bv_val = begin;
+ *serial = ber_dupbv(NULL, &bv);
+
+ /* now extract the issuer, remember p was at the dollar sign */
+ begin = p+1;
+ end = assertion->bv_val+assertion->bv_len-1;
+ while (ASCII_SPACE(*begin))
+ begin++;
+ /* should we trim spaces at the end too? is it safe always? */
+
+ bv.bv_len = end-begin+1;
+ bv.bv_val = begin;
+ dnNormalize( NULL, &bv, issuer_dn );
+
+ return LDAP_SUCCESS;
+}
+
+static int
+certificateExactMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ X509 *xcert;
+ unsigned char *p = value->bv_val;
+ struct berval *serial;
+ struct berval *issuer_dn;
+ struct berval *asserted_serial;
+ struct berval *asserted_issuer_dn;
+ int ret;
+
+ xcert = d2i_X509(NULL, &p, value->bv_len);
+ if ( !xcert ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactMatch: error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
+ "error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ serial = asn1_integer2str(xcert->cert_info->serialNumber);
+ issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
+
+ X509_free(xcert);
+
+ serial_and_issuer_parse(assertedValue,
+ &asserted_serial,
+ &asserted_issuer_dn);
+
+ ret = integerMatch(
+ matchp,
+ flags,
+ slap_schema.si_syn_integer,
+ slap_schema.si_mr_integerMatch,
+ serial,
+ asserted_serial);
+ if ( ret == LDAP_SUCCESS ) {
+ if ( *matchp == 0 ) {
+ /* We need to normalize everything for dnMatch */
+ ret = dnMatch(
+ matchp,
+ flags,
+ slap_schema.si_syn_distinguishedName,
+ slap_schema.si_mr_distinguishedNameMatch,
+ issuer_dn,
+ asserted_issuer_dn);
+ }
+ }
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactMatch: %d\n %s $ %s\n %s $ %s\n",
+ *matchp, serial->bv_val, issuer_dn->bv_val,
+ asserted->serial->bv_val, asserted_issuer_dn->bv_val));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactMatch "
+ "%d\n\t\"%s $ %s\"\n",
+ *matchp, serial->bv_val, issuer_dn->bv_val );
+ Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n",
+ asserted_serial->bv_val, asserted_issuer_dn->bv_val,
+ NULL );
+#endif
+
+ ber_bvfree(serial);
+ ber_bvfree(issuer_dn);
+ ber_bvfree(asserted_serial);
+ ber_bvfree(asserted_issuer_dn);
+
+ return ret;
+}
+
+/*
+ * Index generation function
+ * We just index the serials, in most scenarios the issuer DN is one of
+ * a very small set of values.
+ */
+static int certificateExactIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keysp )
+{
+ int i;
+ BerVarray keys;
+ X509 *xcert;
+ unsigned char *p;
+ struct berval * serial;
+
+ /* we should have at least one value at this point */
+ assert( values != NULL && values[0].bv_val != NULL );
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ /* empty -- just count them */
+ }
+
+ keys = ch_malloc( sizeof( struct berval ) * (i+1) );
+
+ for( i=0; values[i].bv_val != NULL; i++ ) {
+ p = values[i].bv_val;
+ xcert = d2i_X509(NULL, &p, values[i].bv_len);
+ if ( !xcert ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactIndexer: error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
+ "error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL),
+ NULL, NULL );
+#endif
+ /* Do we leak keys on error? */
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ serial = asn1_integer2str(xcert->cert_info->serialNumber);
+ X509_free(xcert);
+ integerNormalize( slap_schema.si_syn_integer,
+ serial,
+ &keys[i] );
+ ber_bvfree(serial);
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactIndexer: returning: %s\n",
+ keys[i].bv_val));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
+ "returning: %s\n",
+ keys[i].bv_val,
+ NULL, NULL );
+#endif
+ }
+
+ keys[i].bv_val = NULL;
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+/* We think this is always called with a value in matching rule syntax */
+static int certificateExactFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keysp )
+{
+ BerVarray keys;
+ struct berval *asserted_serial;
+ struct berval *asserted_issuer_dn;
+
+ serial_and_issuer_parse(assertValue,
+ &asserted_serial,
+ &asserted_issuer_dn);
+
+ keys = ch_malloc( sizeof( struct berval ) * 2 );
+ integerNormalize( syntax, asserted_serial, &keys[0] );
+ keys[1].bv_val = NULL;
+ *keysp = keys;
+
+ ber_bvfree(asserted_serial);
+ ber_bvfree(asserted_issuer_dn);
+ return LDAP_SUCCESS;
+}
+#endif
+
+static int
+check_time_syntax (struct berval *val,
+ int start,
+ int *parts)
+{
+ static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
+ static int mdays[2][12] = {
+ /* non-leap years */
+ { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
+ /* leap years */
+ { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
+ };
+ char *p, *e;
+ int part, c, tzoffset, leapyear = 0 ;
+
+ if( val->bv_len == 0 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ p = (char *)val->bv_val;
+ e = p + val->bv_len;
+
+ /* Ignore initial whitespace */
+ while ( ( p < e ) && ASCII_SPACE( *p ) ) {
+ p++;
+ }
+
+ if (e - p < 13 - (2 * start)) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for (part = 0; part < 9; part++) {
+ parts[part] = 0;
+ }
+
+ for (part = start; part < 7; part++) {
+ c = *p;
+ if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
+ part++;
+ break;
+ }
+ p++;
+ c -= '0';
+ if (p == e) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ if (c < 0 || c > 9) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ parts[part] = c;
+
+ c = *p++ - '0';
+ if (p == e) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ if (c < 0 || c > 9) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ parts[part] *= 10;
+ parts[part] += c;
+
+ if (part == 2 || part == 3) {
+ parts[part]--;
+ }
+ if (parts[part] < 0) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ if (parts[part] > ceiling[part]) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ /* leapyear check for the Gregorian calendar (year>1581) */
+ if (((parts[1] % 4 == 0) && (parts[1] != 0)) ||
+ ((parts[0] % 4 == 0) && (parts[1] == 0)))
+ {
+ leapyear = 1;
+ }
+
+ if (parts[3] > mdays[leapyear][parts[2]]) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ c = *p++;
+ if (c == 'Z') {
+ tzoffset = 0; /* UTC */
+ } else if (c != '+' && c != '-') {
+ return LDAP_INVALID_SYNTAX;
+ } else {
+ if (c == '-') {
+ tzoffset = -1;
+ } else /* c == '+' */ {
+ tzoffset = 1;
+ }
+
+ if (p > e - 4) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for (part = 7; part < 9; part++) {
+ c = *p++ - '0';
+ if (c < 0 || c > 9) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ parts[part] = c;
+
+ c = *p++ - '0';
+ if (c < 0 || c > 9) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ parts[part] *= 10;
+ parts[part] += c;
+ if (parts[part] < 0 || parts[part] > ceiling[part]) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+ }
+
+ /* Ignore trailing whitespace */
+ while ( ( p < e ) && ASCII_SPACE( *p ) ) {
+ p++;
+ }
+ if (p != e) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ switch ( tzoffset ) {
+ case -1: /* negativ offset to UTC, ie west of Greenwich */
+ parts[4] += parts[7];
+ parts[5] += parts[8];
+ for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
+ if (part != 3) {
+ c = ceiling[part];
+ } else {
+ c = mdays[leapyear][parts[2]];
+ }
+ if (parts[part] > c) {
+ parts[part] -= c + 1;
+ parts[part - 1]++;
+ }
+ }
+ break;
+ case 1: /* positive offset to UTC, ie east of Greenwich */
+ parts[4] -= parts[7];
+ parts[5] -= parts[8];
+ for (part = 6; --part > 0; ) {
+ if (part != 3) {
+ c = ceiling[part];
+ } else {
+ /* first arg to % needs to be non negativ */
+ c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
+ }
+ if (parts[part] < 0) {
+ parts[part] += c + 1;
+ parts[part - 1]--;
+ }
+ }
+ break;
+ case 0: /* already UTC */
+ break;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+utcTimeNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ int parts[9], rc;
+
+ rc = check_time_syntax(val, 1, parts);
+ if (rc != LDAP_SUCCESS) {
+ return rc;
+ }
+
+ normalized->bv_val = ch_malloc( 14 );
+ if ( normalized->bv_val == NULL ) {
+ return LBER_ERROR_MEMORY;
+ }
+
+ sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
+ parts[1], parts[2] + 1, parts[3] + 1,
+ parts[4], parts[5], parts[6] );
+ normalized->bv_len = 13;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+utcTimeValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int parts[9];
+
+ return check_time_syntax(in, 1, parts);
+}
+
+static int
+generalizedTimeValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int parts[9];
+
+ return check_time_syntax(in, 0, parts);
+}
+
+static int
+generalizedTimeNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval *normalized )
+{
+ int parts[9], rc;
+
+ rc = check_time_syntax(val, 0, parts);
+ if (rc != LDAP_SUCCESS) {
+ return rc;
+ }
+
+ normalized->bv_val = ch_malloc( 16 );
+ if ( normalized->bv_val == NULL ) {
+ return LBER_ERROR_MEMORY;
+ }
+
+ sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
+ parts[0], parts[1], parts[2] + 1, parts[3] + 1,
+ parts[4], parts[5], parts[6] );
+ normalized->bv_len = 15;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+nisNetgroupTripleValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ char *p, *e;
+ int commas = 0;
+
+ if ( val->bv_len == 0 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ p = (char *)val->bv_val;
+ e = p + val->bv_len;
+
+ if ( *p != '(' /*')'*/ ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ for ( p++; ( p < e ) && ( *p != /*'('*/ ')' ); p++ ) {
+ if ( *p == ',' ) {
+ commas++;
+ if ( commas > 2 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ } else if ( !ATTR_CHAR( *p ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ if ( ( commas != 2 ) || ( *p != /*'('*/ ')' ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ p++;
+
+ if (p != e) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+bootParameterValidate(
+ Syntax *syntax,
+ struct berval *val )
+{
+ char *p, *e;
+
+ if ( val->bv_len == 0 ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ p = (char *)val->bv_val;
+ e = p + val->bv_len;
+
+ /* key */
+ for (; ( p < e ) && ( *p != '=' ); p++ ) {
+ if ( !ATTR_CHAR( *p ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ if ( *p != '=' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* server */
+ for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
+ if ( !ATTR_CHAR( *p ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ if ( *p != ':' ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* path */
+ for ( p++; p < e; p++ ) {
+ if ( !ATTR_CHAR( *p ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static struct syntax_defs_rec {
+ char *sd_desc;
+#define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
+#define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
+ int sd_flags;
+ slap_syntax_validate_func *sd_validate;
+ slap_syntax_transform_func *sd_normalize;
+ slap_syntax_transform_func *sd_pretty;
+#ifdef SLAPD_BINARY_CONVERSION
+ slap_syntax_transform_func *sd_ber2str;
+ slap_syntax_transform_func *sd_str2ber;
+#endif
+} syntax_defs[] = {
+ {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
+ X_BINARY X_NOT_H_R ")",
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
+ X_NOT_H_R ")",
+ SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
+ X_NOT_H_R ")",
+ SLAP_SYNTAX_BER, berValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
+ 0, bitStringValidate, bitStringNormalize, NULL },
+ {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
+ 0, booleanValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
+ X_BINARY X_NOT_H_R ")",
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
+ X_BINARY X_NOT_H_R ")",
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
+ X_BINARY X_NOT_H_R ")",
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
+ 0, countryStringValidate, IA5StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
+ 0, dnValidate, dnNormalize2, dnPretty2},
+ {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
+ 0, UTF8StringValidate, UTF8StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
+ 0, printablesStringValidate, IA5StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
+ SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
+ 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
+ 0, IA5StringValidate, IA5StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
+ 0, integerValidate, integerNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
+ SLAP_SYNTAX_BLOB, blobValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
+ 0, nameUIDValidate, nameUIDNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
+ 0, numericStringValidate, numericStringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
+ 0, oidValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
+ 0, IA5StringValidate, IA5StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
+ 0, blobValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
+ 0, UTF8StringValidate, UTF8StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
+ 0, printableStringValidate, IA5StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' "
+ X_BINARY X_NOT_H_R ")",
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
+ X_BINARY X_NOT_H_R ")",
+ SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
+ 0, printableStringValidate, IA5StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
+ 0, printablesStringValidate, IA5StringNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
+ 0, utcTimeValidate, utcTimeNormalize, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
+ 0, NULL, NULL, NULL},
+ {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
+ 0, NULL, NULL, NULL},
+
+ /* RFC 2307 NIS Syntaxes */
+ {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
+ 0, nisNetgroupTripleValidate, NULL, NULL},
+ {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
+ 0, bootParameterValidate, NULL, NULL},
+
+#ifdef HAVE_TLS
+ /* From PKIX */
+ /* These OIDs are not published yet, but will be in the next
+ * I-D for PKIX LDAPv3 schema as have been advanced by David
+ * Chadwick in private mail.
+ */
+ {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )",
+ 0, NULL, NULL, NULL},
+#endif
+
+ /* OpenLDAP Experimental Syntaxes */
+#ifdef SLAPD_ACI_ENABLED
+ {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
+ SLAP_SYNTAX_HIDE,
+ UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
+ NULL, NULL},
+#endif
+
+#ifdef SLAPD_AUTHPASSWD
+ /* needs updating */
+ {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
+#endif
+
+ /* OpenLDAP Void Syntax */
+ {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
+ SLAP_SYNTAX_HIDE, inValidate, NULL, NULL},
+ {NULL, 0, NULL, NULL, NULL}
+};
+
+/*
+ * Other matching rules in X.520 that we do not use (yet):
+ *
+ * 2.5.13.9 numericStringOrderingMatch
+ * 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.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
+ */
+static struct mrule_defs_rec {
+ char * mrd_desc;
+ slap_mask_t mrd_usage;
+ slap_mr_convert_func * mrd_convert;
+ slap_mr_normalize_func * mrd_normalize;
+ slap_mr_match_func * mrd_match;
+ slap_mr_indexer_func * mrd_indexer;
+ slap_mr_filter_func * mrd_filter;
+
+ char * mrd_associated;
+} mrule_defs[] = {
+ /*
+ * EQUALITY matching rules must be listed after associated APPROX
+ * matching rules. So, we list all APPROX matching rules first.
+ */
+ {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
+ NULL, NULL,
+ directoryStringApproxMatch,
+ directoryStringApproxIndexer,
+ directoryStringApproxFilter,
+ NULL},
+
+ {"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT,
+ NULL, NULL,
+ IA5StringApproxMatch,
+ IA5StringApproxIndexer,
+ IA5StringApproxFilter,
+ NULL},
+
+ /*
+ * Other matching rules
+ */
+
+ {"( 2.5.13.0 NAME 'objectIdentifierMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ objectIdentifierMatch, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
+ NULL},
+
+ {"( 2.5.13.1 NAME 'distinguishedNameMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ dnMatch, dnIndexer, dnFilter,
+ NULL},
+
+ {"( 2.5.13.2 NAME 'caseIgnoreMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
+ NULL, NULL,
+ caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
+ directoryStringApproxMatchOID },
+
+ {"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ SLAP_MR_ORDERING,
+ NULL, NULL,
+ caseIgnoreOrderingMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ SLAP_MR_SUBSTR | SLAP_MR_EXT,
+ NULL, NULL,
+ caseExactIgnoreSubstringsMatch,
+ caseExactIgnoreSubstringsIndexer,
+ caseExactIgnoreSubstringsFilter,
+ NULL},
+
+ {"( 2.5.13.5 NAME 'caseExactMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ caseExactMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
+ directoryStringApproxMatchOID },
+
+ {"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
+ SLAP_MR_ORDERING,
+ NULL, NULL,
+ caseExactOrderingMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ SLAP_MR_SUBSTR | SLAP_MR_EXT,
+ NULL, NULL,
+ caseExactIgnoreSubstringsMatch,
+ caseExactIgnoreSubstringsIndexer,
+ caseExactIgnoreSubstringsFilter,
+ NULL},
+
+ {"( 2.5.13.8 NAME 'numericStringMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
+ NULL, NULL,
+ caseIgnoreIA5Match,
+ caseIgnoreIA5Indexer,
+ caseIgnoreIA5Filter,
+ NULL},
+
+ {"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ SLAP_MR_SUBSTR | SLAP_MR_EXT,
+ NULL, NULL,
+ caseIgnoreIA5SubstringsMatch,
+ caseIgnoreIA5SubstringsIndexer,
+ caseIgnoreIA5SubstringsFilter,
+ NULL},
+
+ {"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
+ NULL, NULL,
+ caseIgnoreListMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ SLAP_MR_SUBSTR | SLAP_MR_EXT,
+ NULL, NULL,
+ caseIgnoreListSubstringsMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.13 NAME 'booleanMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ booleanMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.14 NAME 'integerMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ integerMatch, integerIndexer, integerFilter,
+ NULL},
+
+ {"( 2.5.13.16 NAME 'bitStringMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ bitStringMatch, bitStringIndexer, bitStringFilter,
+ NULL},
+
+ {"( 2.5.13.17 NAME 'octetStringMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ octetStringMatch, octetStringIndexer, octetStringFilter,
+ NULL},
+
+ {"( 2.5.13.20 NAME 'telephoneNumberMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
+ NULL, NULL,
+ telephoneNumberMatch,
+ telephoneNumberIndexer,
+ telephoneNumberFilter,
+ NULL},
+
+ {"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ SLAP_MR_SUBSTR | SLAP_MR_EXT,
+ NULL, NULL,
+ telephoneNumberSubstringsMatch,
+ telephoneNumberSubstringsIndexer,
+ telephoneNumberSubstringsFilter,
+ NULL},
+
+ {"( 2.5.13.22 NAME 'presentationAddressMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ NULL, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.23 NAME 'uniqueMemberMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ uniqueMemberMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.24 NAME 'protocolInformationMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ protocolInformationMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.27 NAME 'generalizedTimeMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ generalizedTimeMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
+ SLAP_MR_ORDERING,
+ NULL, NULL,
+ generalizedTimeOrderingMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ integerFirstComponentMatch, NULL, NULL,
+ NULL},
+
+ {"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ objectIdentifierFirstComponentMatch, NULL, NULL,
+ NULL},
+
+#ifdef HAVE_TLS
+ {"( 2.5.13.34 NAME 'certificateExactMatch' "
+ "SYNTAX 1.2.826.0.1.3344810.7.1 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ certificateExactConvert, NULL,
+ certificateExactMatch,
+ certificateExactIndexer, certificateExactFilter,
+ NULL},
+#endif
+
+ {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ caseExactIA5Match, caseExactIA5Indexer, caseExactIA5Filter,
+ IA5StringApproxMatchOID },
+
+ {"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
+ NULL, NULL,
+ caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
+ IA5StringApproxMatchOID },
+
+ {"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ SLAP_MR_SUBSTR,
+ NULL, NULL,
+ caseIgnoreIA5SubstringsMatch,
+ caseIgnoreIA5SubstringsIndexer,
+ caseIgnoreIA5SubstringsFilter,
+ NULL},
+
+ {"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
+ SLAP_MR_SUBSTR,
+ NULL, NULL,
+ caseExactIA5SubstringsMatch,
+ caseExactIA5SubstringsIndexer,
+ caseExactIA5SubstringsFilter,
+ NULL},
+
+#ifdef SLAPD_AUTHPASSWD
+ /* needs updating */
+ {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
+ SLAP_MR_EQUALITY,
+ NULL, NULL,
+ authPasswordMatch, NULL, NULL,
+ NULL},
+#endif
+
+#ifdef SLAPD_ACI_ENABLED
+ {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' "
+ "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )",
+ SLAP_MR_EQUALITY,
+ NULL, NULL,
+ OpenLDAPaciMatch, NULL, NULL,
+ NULL},
+#endif
+
+ {"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
+ SLAP_MR_EXT,
+ NULL, NULL,
+ integerBitAndMatch, NULL, NULL,
+ NULL},
+
+ {"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
+ SLAP_MR_EXT,
+ NULL, NULL,
+ integerBitOrMatch, NULL, NULL,
+ NULL},
+
+ {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL}
+};
+
+int
+slap_schema_init( void )
+{
+ int res;
+ int i;
+
+ /* we should only be called once (from main) */
+ assert( schema_init_done == 0 );
+
+ for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
+ res = register_syntax( syntax_defs[i].sd_desc,
+ syntax_defs[i].sd_flags,
+ syntax_defs[i].sd_validate,
+ syntax_defs[i].sd_normalize,
+ syntax_defs[i].sd_pretty
+#ifdef SLAPD_BINARY_CONVERSION
+ ,
+ syntax_defs[i].sd_ber2str,
+ syntax_defs[i].sd_str2ber
+#endif
+ );
+
+ if ( res ) {
+ fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
+ syntax_defs[i].sd_desc );
+ return LDAP_OTHER;
+ }
+ }
+
+ for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
+ if( mrule_defs[i].mrd_usage == SLAP_MR_NONE ) {
+ fprintf( stderr,
+ "slap_schema_init: Ingoring unusable matching rule %s\n",
+ mrule_defs[i].mrd_desc );
+ continue;
+ }
+
+ res = register_matching_rule(
+ mrule_defs[i].mrd_desc,
+ mrule_defs[i].mrd_usage,
+ mrule_defs[i].mrd_convert,
+ mrule_defs[i].mrd_normalize,
+ mrule_defs[i].mrd_match,
+ mrule_defs[i].mrd_indexer,
+ mrule_defs[i].mrd_filter,
+ mrule_defs[i].mrd_associated );
+
+ if ( res ) {
+ fprintf( stderr,
+ "slap_schema_init: Error registering matching rule %s\n",
+ mrule_defs[i].mrd_desc );
+ return LDAP_OTHER;
+ }
+ }
+
+ res = slap_schema_load();
+ schema_init_done = 1;
+ return res;
+}
+
+void
+schema_destroy( void )
+{
+ oidm_destroy();
+ oc_destroy();
+ at_destroy();
+ mr_destroy();
+ syn_destroy();
+}
--- /dev/null
+/* schema_init.c - init builtin schema */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "ldap_pvt.h"
+#include "ldap_pvt_uc.h"
+
+int schema_init_done = 0;
+
+struct slap_internal_schema slap_schema;
+
+static int
+objectClassMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ struct berval *a = (struct berval *) assertedValue;
+ ObjectClass *oc = oc_bvfind( value );
+ ObjectClass *asserted = oc_bvfind( a );
+
+#if 1
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "> objectClassMatch(%s, %s)\n",
+ value->bv_val, a->bv_val ));
+#else
+ Debug( LDAP_DEBUG_TRACE, "> objectClassMatch(%s,%s)\n",
+ value->bv_val, a->bv_val, 0 );
+#endif
+#endif
+
+ if( asserted == NULL ) {
+ if( OID_LEADCHAR( *a->bv_val ) ) {
+ /* OID form, return FALSE */
+ *matchp = 1;
+ return LDAP_SUCCESS;
+ }
+
+ /* desc form, return undefined */
+ return SLAPD_COMPARE_UNDEFINED;
+ }
+
+ if ( oc == NULL ) {
+ /* unrecognized stored value */
+ return SLAPD_COMPARE_UNDEFINED;
+ }
+
+ if( SLAP_IS_MR_VALUE_SYNTAX_MATCH( flags ) ) {
+ *matchp = ( asserted != oc );
+ } else {
+ *matchp = !is_object_subclass( asserted, oc );
+ }
+
+#if 1
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "< objectClassMatch(%s, %s) = %d\n",
+ value->bv_val, a->bv_val, *matchp ));
+#else
+ Debug( LDAP_DEBUG_TRACE, "< objectClassMatch(%s,%s) = %d\n",
+ value->bv_val, a->bv_val, *matchp );
+#endif
+#endif
+
+ return LDAP_SUCCESS;
+}
+
+#if 1
+#define structuralObjectClassMatch objectClassMatch
+#else
+static int
+structuralObjectClassMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ struct berval *a = (struct berval *) assertedValue;
+ ObjectClass *oc = oc_bvfind( value );
+ ObjectClass *asserted = oc_bvfind( a );
+
+#if 1
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "> structuralObjectClassMatch(%s, %s)\n",
+ value->bv_val, a->bv_val ));
+#else
+ Debug( LDAP_DEBUG_TRACE, "> structuralObjectClassMatch(%s,%s)\n",
+ value->bv_val, a->bv_val, 0 );
+#endif
+#endif
+
+ if( asserted == NULL ) {
+ if( OID_LEADCHAR( *a->bv_val ) ) {
+ /* OID form, return FALSE */
+ *matchp = 1;
+ return LDAP_SUCCESS;
+ }
+
+ /* desc form, return undefined */
+ return SLAPD_COMPARE_UNDEFINED;
+ }
+
+ if ( oc == NULL ) {
+ /* unrecognized stored value */
+ return SLAPD_COMPARE_UNDEFINED;
+ }
+
+ *matchp = ( asserted != oc );
+
+#if 1
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "< structuralObjectClassMatch( %s, %s ) = %d\n",
+ value->bv_val, a->bv_val, *matchp ));
+#else
+ Debug( LDAP_DEBUG_TRACE, "< structuralObjectClassMatch(%s,%s) = %d\n",
+ value->bv_val, a->bv_val, *matchp );
+#endif
+#endif
+
+ return LDAP_SUCCESS;
+}
+#endif
+
+static ObjectClassSchemaCheckFN rootDseObjectClass;
+static ObjectClassSchemaCheckFN aliasObjectClass;
+static ObjectClassSchemaCheckFN referralObjectClass;
+static ObjectClassSchemaCheckFN subentryObjectClass;
+static ObjectClassSchemaCheckFN dynamicObjectClass;
+
+static struct slap_schema_oc_map {
+ char *ssom_name;
+ char *ssom_defn;
+ ObjectClassSchemaCheckFN *ssom_check;
+ slap_mask_t ssom_flags;
+ size_t ssom_offset;
+} oc_map[] = {
+ { "top", "( 2.5.6.0 NAME 'top' "
+ "DESC 'top of the superclass chain' "
+ "ABSTRACT MUST objectClass )",
+ 0, 0, offsetof(struct slap_internal_schema, si_oc_top) },
+ { "extensibleObject", "( 1.3.6.1.4.1.1466.101.120.111 "
+ "NAME 'extensibleObject' "
+ "DESC 'RFC2252: extensible object' "
+ "SUP top AUXILIARY )",
+ 0, 0, offsetof(struct slap_internal_schema, si_oc_extensibleObject) },
+ { "alias", "( 2.5.6.1 NAME 'alias' "
+ "DESC 'RFC2256: an alias' "
+ "SUP top STRUCTURAL "
+ "MUST aliasedObjectName )",
+ aliasObjectClass, SLAP_OC_ALIAS,
+ offsetof(struct slap_internal_schema, si_oc_alias) },
+ { "referral", "( 2.16.840.1.113730.3.2.6 NAME 'referral' "
+ "DESC 'namedref: named subordinate referral' "
+ "SUP top STRUCTURAL MUST ref )",
+ referralObjectClass, SLAP_OC_REFERRAL,
+ offsetof(struct slap_internal_schema, si_oc_referral) },
+ { "LDAProotDSE", "( 1.3.6.1.4.1.4203.1.4.1 "
+ "NAME ( 'OpenLDAProotDSE' 'LDAProotDSE' ) "
+ "DESC 'OpenLDAP Root DSE object' "
+ "SUP top STRUCTURAL MAY cn )",
+ rootDseObjectClass, 0,
+ offsetof(struct slap_internal_schema, si_oc_rootdse) },
+ { "subentry", "( 2.5.20.0 NAME 'subentry' "
+ "SUP top STRUCTURAL "
+ "MUST ( cn $ subtreeSpecification ) )",
+ subentryObjectClass, SLAP_OC_SUBENTRY,
+ offsetof(struct slap_internal_schema, si_oc_subentry) },
+ { "subschema", "( 2.5.20.1 NAME 'subschema' "
+ "DESC 'RFC2252: controlling subschema (sub)entry' "
+ "AUXILIARY "
+ "MAY ( dITStructureRules $ nameForms $ ditContentRules $ "
+ "objectClasses $ attributeTypes $ matchingRules $ "
+ "matchingRuleUse ) )",
+ subentryObjectClass, 0,
+ offsetof(struct slap_internal_schema, si_oc_subschema) },
+ { "monitor", "( 1.3.6.1.4.1.4203.666.3.2 NAME 'monitor' "
+ "DESC 'OpenLDAP system monitoring' "
+ "STRUCTURAL "
+ "MUST cn )",
+ 0, 0, offsetof(struct slap_internal_schema, si_oc_monitor) },
+ { NULL, NULL, NULL, 0, 0 }
+};
+
+static AttributeTypeSchemaCheckFN rootDseAttribute;
+static AttributeTypeSchemaCheckFN aliasAttribute;
+static AttributeTypeSchemaCheckFN referralAttribute;
+static AttributeTypeSchemaCheckFN subentryAttribute;
+static AttributeTypeSchemaCheckFN administrativeRoleAttribute;
+static AttributeTypeSchemaCheckFN dynamicAttribute;
+
+static struct slap_schema_ad_map {
+ char *ssam_name;
+ char *ssam_defn;
+ AttributeTypeSchemaCheckFN *ssam_check;
+ slap_mask_t ssam_flags;
+ slap_mr_match_func *ssam_match;
+ slap_mr_indexer_func *ssam_indexer;
+ slap_mr_filter_func *ssam_filter;
+ size_t ssam_offset;
+} ad_map[] = {
+ { "objectClass", "( 2.5.4.0 NAME 'objectClass' "
+ "DESC 'RFC2256: object classes of the entity' "
+ "EQUALITY objectIdentifierMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
+ NULL, 0, objectClassMatch, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_objectClass) },
+
+ /* user entry operational attributes */
+ { "structuralObjectClass", "( 2.5.21.9 NAME 'structuralObjectClass' "
+ "DESC 'X.500(93): structural object class of entry' "
+ "EQUALITY objectIdentifierMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
+ "NO-USER-MODIFICATION SINGLE-VALUE USAGE directoryOperation )",
+ NULL, 0, structuralObjectClassMatch, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_structuralObjectClass) },
+ { "createTimestamp", "( 2.5.18.1 NAME 'createTimestamp' "
+ "DESC 'RFC2252: time which object was created' "
+ "EQUALITY generalizedTimeMatch "
+ "ORDERING generalizedTimeOrderingMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
+ "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_createTimestamp) },
+ { "modifyTimestamp", "( 2.5.18.2 NAME 'modifyTimestamp' "
+ "DESC 'RFC2252: time which object was last modified' "
+ "EQUALITY generalizedTimeMatch "
+ "ORDERING generalizedTimeOrderingMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
+ "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_modifyTimestamp) },
+ { "creatorsName", "( 2.5.18.3 NAME 'creatorsName' "
+ "DESC 'RFC2252: name of creator' "
+ "EQUALITY distinguishedNameMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
+ "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_creatorsName) },
+ { "modifiersName", "( 2.5.18.4 NAME 'modifiersName' "
+ "DESC 'RFC2252: name of last modifier' "
+ "EQUALITY distinguishedNameMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
+ "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_modifiersName) },
+ { "hasSubordinates", "( 2.5.18.9 NAME 'hasSubordinates' "
+ "DESC 'X.501: entry has children' "
+ "EQUALITY booleanMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
+ "SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_hasSubordinates) },
+ { "subschemaSubentry", "( 2.5.18.10 NAME 'subschemaSubentry' "
+ "DESC 'RFC2252: name of controlling subschema entry' "
+ "EQUALITY distinguishedNameMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
+ "SINGLE-VALUE USAGE directoryOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_subschemaSubentry) },
+
+ /* root DSE attributes */
+ { "altServer", "( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer' "
+ "DESC 'RFC2252: alternative servers' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_altServer) },
+ { "namingContexts", "( 1.3.6.1.4.1.1466.101.120.5 "
+ "NAME 'namingContexts' "
+ "DESC 'RFC2252: naming contexts' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_namingContexts) },
+ { "supportedControl", "( 1.3.6.1.4.1.1466.101.120.13 "
+ "NAME 'supportedControl' "
+ "DESC 'RFC2252: supported controls' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_supportedControl) },
+ { "supportedExtension", "( 1.3.6.1.4.1.1466.101.120.7 "
+ "NAME 'supportedExtension' "
+ "DESC 'RFC2252: supported extended operations' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_supportedExtension) },
+ { "supportedLDAPVersion", "( 1.3.6.1.4.1.1466.101.120.15 "
+ "NAME 'supportedLDAPVersion' "
+ "DESC 'RFC2252: supported LDAP versions' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_supportedLDAPVersion) },
+ { "supportedSASLMechanisms", "( 1.3.6.1.4.1.1466.101.120.14 "
+ "NAME 'supportedSASLMechanisms' "
+ "DESC 'RFC2252: supported SASL mechanisms'"
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_supportedSASLMechanisms) },
+ { "supportedFeatures", "( 1.3.6.1.4.1.4203.1.3.5 "
+ "NAME 'supportedFeatures' "
+ "DESC 'features supported by the server' "
+ "EQUALITY objectIdentifierMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
+ "USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_supportedFeatures) },
+ { "vendorName", "( 1.3.6.1.1.4 NAME 'vendorName' "
+ "DESC 'RFC3045: name of implementation vendor' "
+ "EQUALITY 1.3.6.1.4.1.1466.109.114.1 "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
+ "SINGLE-VALUE NO-USER-MODIFICATION "
+ "USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_vendorName) },
+ { "vendorVersion", "( 1.3.6.1.1.5 NAME 'vendorVersion' "
+ "DESC 'RFC3045: version of implementation' "
+ "EQUALITY 1.3.6.1.4.1.1466.109.114.1 "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
+ "SINGLE-VALUE NO-USER-MODIFICATION "
+ "USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_vendorVersion) },
+
+ /* subentry attributes */
+ { "administrativeRole", "( 2.5.18.5 NAME 'administrativeRole' "
+ "EQUALITY objectIdentifierMatch "
+ "USAGE directoryOperation "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
+ administrativeRoleAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_administrativeRole) },
+ { "subtreeSpecification", "( 2.5.18.6 NAME 'subtreeSpecification' "
+ "SINGLE-VALUE "
+ "USAGE directoryOperation "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.45 )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_subtreeSpecification) },
+
+ /* subschema subentry attributes */
+ { "ditStructureRules", "( 2.5.21.1 NAME 'dITStructureRules' "
+ "DESC 'RFC2252: DIT structure rules' "
+ "EQUALITY integerFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 "
+ "USAGE directoryOperation ) ",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_ditStructureRules) },
+ { "ditContentRules", "( 2.5.21.2 NAME 'dITContentRules' "
+ "DESC 'RFC2252: DIT content rules' "
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_ditContentRules) },
+ { "matchingRules", "( 2.5.21.4 NAME 'matchingRules' "
+ "DESC 'RFC2252: matching rules' "
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_matchingRules) },
+ { "attributeTypes", "( 2.5.21.5 NAME 'attributeTypes' "
+ "DESC 'RFC2252: attribute types' "
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_attributeTypes) },
+ { "objectClasses", "( 2.5.21.6 NAME 'objectClasses' "
+ "DESC 'RFC2252: object classes' "
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_objectClasses) },
+ { "nameForms", "( 2.5.21.7 NAME 'nameForms' "
+ "DESC 'RFC2252: name forms ' "
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_nameForms) },
+ { "matchingRuleUse", "( 2.5.21.8 NAME 'matchingRuleUse' "
+ "DESC 'RFC2252: matching rule uses' "
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_matchingRuleUse) },
+
+ { "ldapSyntaxes", "( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes' "
+ "DESC 'RFC2252: LDAP syntaxes' "
+ "EQUALITY objectIdentifierFirstComponentMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )",
+ subentryAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_ldapSyntaxes) },
+
+ /* knowledge information */
+ { "aliasedObjectName", "( 2.5.4.1 "
+ "NAME ( 'aliasedObjectName' 'aliasedEntryName' ) "
+ "DESC 'RFC2256: name of aliased object' "
+ "EQUALITY distinguishedNameMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )",
+ aliasAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_aliasedObjectName) },
+ { "ref", "( 2.16.840.1.113730.3.1.34 NAME 'ref' "
+ "DESC 'namedref: subordinate referral URL' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
+ "USAGE distributedOperation )",
+ referralAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_ref) },
+
+ /* access control internals */
+ { "entry", "( 1.3.6.1.4.1.4203.1.3.1 "
+ "NAME 'entry' "
+ "DESC 'OpenLDAP ACL entry pseudo-attribute' "
+ "SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
+ "SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_entry) },
+ { "children", "( 1.3.6.1.4.1.4203.1.3.2 "
+ "NAME 'children' "
+ "DESC 'OpenLDAP ACL children pseudo-attribute' "
+ "SYNTAX 1.3.6.1.4.1.4203.1.1.1 "
+ "SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_children) },
+
+#ifdef SLAPD_ACI_ENABLED
+ { "OpenLDAPaci", "( 1.3.6.1.4.1.4203.666.1.5 "
+ "NAME 'OpenLDAPaci' "
+ "DESC 'OpenLDAP access control information (experimental)' "
+ "EQUALITY OpenLDAPaciMatch "
+ "SYNTAX 1.3.6.1.4.1.4203.666.2.1 "
+ "USAGE directoryOperation )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_aci) },
+#endif
+
+ { "entryTtl", "( 1.3.6.1.4.1.1466.101.119.3 NAME 'entryTtl' "
+ "DESC 'RFC2589: entry time-to-live' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE "
+ "NO-USER-MODIFICATION USAGE dSAOperation )",
+ dynamicAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_entryTtl) },
+ { "dynamicSubtrees", "( 1.3.6.1.4.1.1466.101.119.4 "
+ "NAME 'dynamicSubtrees' "
+ "DESC 'RFC2589: dynamic subtrees' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION "
+ "USAGE dSAOperation )",
+ rootDseAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_dynamicSubtrees) },
+
+ /* userApplication attributes (which system schema depends upon) */
+ { "distinguishedName", "( 2.5.4.49 NAME 'distinguishedName' "
+ "DESC 'RFC2256: common supertype of DN attributes' "
+ "EQUALITY distinguishedNameMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_distinguishedName) },
+ { "name", "( 2.5.4.41 NAME 'name' "
+ "DESC 'RFC2256: common supertype of name attributes' "
+ "EQUALITY caseIgnoreMatch "
+ "SUBSTR caseIgnoreSubstringsMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_name) },
+ { "cn", "( 2.5.4.3 NAME ( 'cn' 'commonName' ) "
+ "DESC 'RFC2256: common name(s) for which the entity is known by' "
+ "SUP name )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_cn) },
+ { "userPassword", "( 2.5.4.35 NAME 'userPassword' "
+ "DESC 'RFC2256/2307: password of user' "
+ "EQUALITY octetStringMatch "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )",
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_userPassword) },
+
+#ifdef SLAPD_AUTHPASSWD
+ { "authPassword", "( 1.3.6.1.4.1.4203.1.3.4 "
+ "NAME 'authPassword' "
+ "DESC 'RFC3112: authentication password attribute' "
+ "EQUALITY 1.3.6.1.4.1.4203.1.2.2 "
+ "SYNTAX 1.3.6.1.4.1.4203.1.1.2 )",
+ NULL, 0,
+ NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_authPassword) },
+ { "supportedAuthPasswordSchemes", "( 1.3.6.1.4.1.4203.1.3.3 "
+ "NAME 'supportedAuthPasswordSchemes' "
+ "DESC 'RFC3112: supported authPassword schemes' "
+ "EQUALITY caseExactIA5Match "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} "
+ "USAGE dSAOperation )",
+ subschemaAttribute, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_authPassword) },
+#endif
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+ { "krbName", NULL,
+ NULL, 0, NULL, NULL, NULL,
+ offsetof(struct slap_internal_schema, si_ad_krbName) },
+#endif
+
+ { NULL, NULL, NULL, 0, NULL, NULL, NULL, 0 }
+};
+
+static AttributeType slap_at_undefined = {
+ { "1.1.1", NULL, NULL, 1, NULL,
+ NULL, NULL, NULL, NULL,
+ 0, 0, 0, 1, 3 }, /* LDAPAttributeType */
+ { sizeof("UNDEFINED")-1, "UNDEFINED" }, /* cname */
+ NULL, /* sup */
+ NULL, /* subtypes */
+ NULL, NULL, NULL, NULL, /* matching rules */
+ NULL, /* syntax (this may need to be defined) */
+ (AttributeTypeSchemaCheckFN *) 0, 0, /* schema check function/mask */
+ NULL, /* next */
+ NULL /* attribute description */
+ /* mutex (don't know how to initialize it :) */
+};
+
+static struct slap_schema_mr_map {
+ char *ssmm_name;
+ size_t ssmm_offset;
+} mr_map[] = {
+ { "distinguishedNameMatch",
+ offsetof(struct slap_internal_schema, si_mr_distinguishedNameMatch) },
+ { "integerMatch",
+ offsetof(struct slap_internal_schema, si_mr_integerMatch) },
+ { NULL, 0 }
+};
+
+static struct slap_schema_syn_map {
+ char *sssm_name;
+ size_t sssm_offset;
+} syn_map[] = {
+ { "1.3.6.1.4.1.1466.115.121.1.12",
+ offsetof(struct slap_internal_schema, si_syn_distinguishedName) },
+ { "1.3.6.1.4.1.1466.115.121.1.27",
+ offsetof(struct slap_internal_schema, si_syn_integer) },
+ { NULL, 0 }
+};
+
+int
+slap_schema_load( void )
+{
+ int i;
+ for( i=0; ad_map[i].ssam_name; i++ ) {
+ if( ad_map[i].ssam_defn != NULL ) {
+ LDAPAttributeType *at;
+ int code;
+ const char *err;
+
+ at = ldap_str2attributetype( ad_map[i].ssam_defn,
+ &code, &err, LDAP_SCHEMA_ALLOW_ALL );
+ if ( !at ) {
+ fprintf( stderr,
+ "slap_schema_load: %s: %s before %s\n",
+ ad_map[i].ssam_name, ldap_scherr2str(code), err );
+ return code;
+ }
+
+ if ( at->at_oid == NULL ) {
+ fprintf( stderr, "slap_schema_load: "
+ "attributeType \"%s\" has no OID\n",
+ ad_map[i].ssam_name );
+ return LDAP_OTHER;
+ }
+
+ code = at_add( at, &err );
+ if ( code ) {
+ fprintf( stderr, "slap_schema_load: "
+ "%s: %s: \"%s\"\n",
+ ad_map[i].ssam_name, scherr2str(code), err );
+ return code;
+ }
+ ldap_memfree( at );
+ }
+ }
+
+ for( i=0; oc_map[i].ssom_name; i++ ) {
+ if( oc_map[i].ssom_defn != NULL ) {
+ LDAPObjectClass *oc;
+ int code;
+ const char *err;
+
+ oc = ldap_str2objectclass( oc_map[i].ssom_defn, &code, &err,
+ LDAP_SCHEMA_ALLOW_ALL );
+ if ( !oc ) {
+ fprintf( stderr, "slap_schema_load: "
+ "%s: %s before %s\n",
+ oc_map[i].ssom_name, ldap_scherr2str(code), err );
+ return code;
+ }
+
+ if ( oc->oc_oid == NULL ) {
+ fprintf( stderr, "slap_schema_load: "
+ "%s: objectclass has no OID\n",
+ oc_map[i].ssom_name );
+ return LDAP_OTHER;
+ }
+
+ code = oc_add(oc,&err);
+ if ( code ) {
+ fprintf( stderr, "slap_schema_load: "
+ "%s: %s: \"%s\"\n",
+ oc_map[i].ssom_name, scherr2str(code), err);
+ return code;
+ }
+
+ ldap_memfree(oc);
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+slap_schema_check( void )
+{
+ int i;
+ /* we should only be called once after schema_init() was called */
+ assert( schema_init_done == 1 );
+
+ for( i=0; syn_map[i].sssm_name; i++ ) {
+ Syntax ** synp = (Syntax **)
+ &(((char *) &slap_schema)[syn_map[i].sssm_offset]);
+
+ assert( *synp == NULL );
+
+ *synp = syn_find( syn_map[i].sssm_name );
+
+ if( *synp == NULL ) {
+ fprintf( stderr, "slap_schema_check: "
+ "No syntax \"%s\" defined in schema\n",
+ syn_map[i].sssm_name );
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ for( i=0; mr_map[i].ssmm_name; i++ ) {
+ MatchingRule ** mrp = (MatchingRule **)
+ &(((char *) &slap_schema)[mr_map[i].ssmm_offset]);
+
+ assert( *mrp == NULL );
+
+ *mrp = mr_find( mr_map[i].ssmm_name );
+
+ if( *mrp == NULL ) {
+ fprintf( stderr, "slap_schema_check: "
+ "No matching rule \"%s\" defined in schema\n",
+ mr_map[i].ssmm_name );
+ return LDAP_INAPPROPRIATE_MATCHING;
+ }
+ }
+
+ slap_at_undefined.sat_syntax = syn_find( SLAPD_OCTETSTRING_SYNTAX );
+ if( slap_at_undefined.sat_syntax == NULL ) {
+ fprintf( stderr, "slap_schema_check: "
+ "No octetString syntax \"" SLAPD_OCTETSTRING_SYNTAX "\"\n" );
+ return LDAP_INVALID_SYNTAX;
+ }
+ slap_schema.si_at_undefined = &slap_at_undefined;
+
+ for( i=0; ad_map[i].ssam_name; i++ ) {
+ int rc;
+ const char *text;
+
+ AttributeDescription ** adp = (AttributeDescription **)
+ &(((char *) &slap_schema)[ad_map[i].ssam_offset]);
+
+ assert( *adp == NULL );
+
+ rc = slap_str2ad( ad_map[i].ssam_name, adp, &text );
+ if( rc != LDAP_SUCCESS ) {
+ fprintf( stderr, "slap_schema_check: "
+ "No attribute \"%s\" defined in schema\n",
+ ad_map[i].ssam_name );
+ return rc;
+ }
+
+ if( ad_map[i].ssam_check ) {
+ /* install check routine */
+ (*adp)->ad_type->sat_check = ad_map[i].ssam_check;
+ }
+ /* install flags */
+ (*adp)->ad_type->sat_flags |= ad_map[i].ssam_flags;
+
+ if( ad_map[i].ssam_match ) {
+ /* install custom matching routine */
+ (*adp)->ad_type->sat_equality->smr_match = ad_map[i].ssam_match;
+ }
+ }
+
+ for( i=0; oc_map[i].ssom_name; i++ ) {
+ ObjectClass ** ocp = (ObjectClass **)
+ &(((char *) &slap_schema)[oc_map[i].ssom_offset]);
+
+ assert( *ocp == NULL );
+
+ *ocp = oc_find( oc_map[i].ssom_name );
+ if( *ocp == NULL ) {
+ fprintf( stderr, "slap_schema_check: "
+ "No objectClass \"%s\" defined in schema\n",
+ oc_map[i].ssom_name );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ if( oc_map[i].ssom_check ) {
+ /* install check routine */
+ (*ocp)->soc_check = oc_map[i].ssom_check;
+ }
+ /* install flags */
+ (*ocp)->soc_flags |= oc_map[i].ssom_flags;
+ }
+
+ ++schema_init_done;
+ return LDAP_SUCCESS;
+}
+
+static int rootDseObjectClass (
+ Backend *be,
+ Entry *e,
+ ObjectClass *oc,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( e->e_nname.bv_len ) {
+ snprintf( textbuf, textlen,
+ "objectClass \"%s\" only allowed in the root DSE",
+ oc->soc_oid );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ /* we should not be called for the root DSE */
+ assert( 0 );
+ return LDAP_SUCCESS;
+}
+
+static int aliasObjectClass (
+ Backend *be,
+ Entry *e,
+ ObjectClass *oc,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_ALIASES(be) ) {
+ snprintf( textbuf, textlen,
+ "objectClass \"%s\" not supported in context",
+ oc->soc_oid );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int referralObjectClass (
+ Backend *be,
+ Entry *e,
+ ObjectClass *oc,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_REFERRALS(be) ) {
+ snprintf( textbuf, textlen,
+ "objectClass \"%s\" not supported in context",
+ oc->soc_oid );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int subentryObjectClass (
+ Backend *be,
+ Entry *e,
+ ObjectClass *oc,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_SUBENTRIES(be) ) {
+ snprintf( textbuf, textlen,
+ "objectClass \"%s\" not supported in context",
+ oc->soc_oid );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ if( oc != slap_schema.si_oc_subentry && !is_entry_subentry( e ) ) {
+ snprintf( textbuf, textlen,
+ "objectClass \"%s\" only allowed in subentries",
+ oc->soc_oid );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int dynamicObjectClass (
+ Backend *be,
+ Entry *e,
+ ObjectClass *oc,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_DYNAMIC(be) ) {
+ snprintf( textbuf, textlen,
+ "objectClass \"%s\" not supported in context",
+ oc->soc_oid );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int rootDseAttribute (
+ Backend *be,
+ Entry *e,
+ Attribute *attr,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( e->e_nname.bv_len ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" only allowed in the root DSE",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ /* we should not be called for the root DSE */
+ assert( 0 );
+ return LDAP_SUCCESS;
+}
+
+static int aliasAttribute (
+ Backend *be,
+ Entry *e,
+ Attribute *attr,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_ALIASES(be) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" not supported in context",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ if( !is_entry_alias( e ) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" only allowed in the alias",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int referralAttribute (
+ Backend *be,
+ Entry *e,
+ Attribute *attr,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_REFERRALS(be) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" not supported in context",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ if( !is_entry_referral( e ) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" only allowed in the referral",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int subentryAttribute (
+ Backend *be,
+ Entry *e,
+ Attribute *attr,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_SUBENTRIES(be) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" not supported in context",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ if( !is_entry_subentry( e ) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" only allowed in the subentry",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int administrativeRoleAttribute (
+ Backend *be,
+ Entry *e,
+ Attribute *attr,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_SUBENTRIES(be) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" not supported in context",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" not supported!",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+}
+
+static int dynamicAttribute (
+ Backend *be,
+ Entry *e,
+ Attribute *attr,
+ const char** text,
+ char *textbuf, size_t textlen )
+{
+ *text = textbuf;
+
+ if( !SLAP_DYNAMIC(be) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" not supported in context",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ if( !is_entry_dynamicObject( e ) ) {
+ snprintf( textbuf, textlen,
+ "attribute \"%s\" only allowed in dynamic object",
+ attr->a_desc->ad_cname.bv_val );
+ return LDAP_OBJECT_CLASS_VIOLATION;
+ }
+
+ return LDAP_SUCCESS;
+}
/* slap.h - stand alone ldap server include file */
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+
+#ifndef _SLAP_H_
+#define _SLAP_H_
-#ifndef _SLDAPD_H_
-#define _SLDAPD_H_
+#include "ldap_defaults.h"
-#define LDAP_SYSLOG
+#include <stdio.h>
+#include <ac/stdlib.h>
+
+#include <sys/types.h>
+#include <ac/syslog.h>
+#include <ac/regex.h>
+#include <ac/socket.h>
+#include <ac/time.h>
+#include <ac/param.h>
-#include <syslog.h>
#include "avl.h"
-#include "lber.h"
-#include "ldap.h"
-#include "lthread.h"
-#include "ldif.h"
-#define DN_DNS 0
-#define DN_X500 1
+#ifndef ldap_debug
+#define ldap_debug slap_debug
+#endif
+
+#include "ldap_log.h"
+
+#include <ldap.h>
+#include <ldap_schema.h>
-#define ON 1
-#define OFF (-1)
+#include "ldap_pvt_thread.h"
+#include "ldap_queue.h"
+LDAP_BEGIN_DECL
/*
- * represents an attribute value assertion (i.e., attr=value)
+ * SLAPD Memory allocation macros
+ *
+ * Unlike ch_*() routines, these routines do not assert() upon
+ * allocation error. They are intended to be used instead of
+ * ch_*() routines where the caller has implemented proper
+ * checking for and handling of allocation errors.
+ *
+ * Patches to convert ch_*() calls to SLAP_*() calls welcomed.
*/
-typedef struct ava {
- char *ava_type;
- struct berval ava_value;
-} Ava;
+#define SLAP_MALLOC(s) ber_memalloc((s))
+#define SLAP_CALLOC(n,s) ber_memcalloc((n),(s))
+#define SLAP_REALLOC(p,s) ber_memrealloc((p),(s))
+#define SLAP_FREE(p) ber_memfree((p))
+#define SLAP_VFREE(v) ber_memvfree((void**)(v))
+#define SLAP_STRDUP(s) ber_strdup((s))
+#define SLAP_STRNDUP(s,l) ber_strndup((s),(l))
+
+#ifdef f_next
+#undef f_next /* name conflict between sys/file.h on SCO and struct filter */
+#endif
+
+#define SERVICE_NAME OPENLDAP_PACKAGE "-slapd"
+#define SLAPD_ANONYMOUS "cn=anonymous"
+
+/* LDAPMod.mod_op value ===> Must be kept in sync with ldap.h!
+ *
+ * This is a value used internally by the backends. It is needed to allow
+ * adding values that already exist without getting an error as required by
+ * modrdn when the new rdn was already an attribute value itself.
+ * JCG 05/1999 (gomez@engr.sgi.com)
+ */
+#define SLAP_MOD_SOFTADD 0x1000
+
+#define MAXREMATCHES (10)
+
+#define SLAP_MAX_WORKER_THREADS (32)
+
+#define SLAP_SB_MAX_INCOMING_DEFAULT ((1<<18) - 1)
+#define SLAP_SB_MAX_INCOMING_AUTH ((1<<24) - 1)
+
+#define SLAP_TEXT_BUFLEN (256)
+
+/* psuedo error code indicating abandoned operation */
+#define SLAPD_ABANDON (-1)
+
+/* psuedo error code indicating disconnect */
+#define SLAPD_DISCONNECT (-2)
+
+
+/* We assume "C" locale, that is US-ASCII */
+#define ASCII_SPACE(c) ( (c) == ' ' )
+#define ASCII_LOWER(c) ( (c) >= 'a' && (c) <= 'z' )
+#define ASCII_UPPER(c) ( (c) >= 'A' && (c) <= 'Z' )
+#define ASCII_ALPHA(c) ( ASCII_LOWER(c) || ASCII_UPPER(c) )
+#define ASCII_DIGIT(c) ( (c) >= '0' && (c) <= '9' )
+#define ASCII_ALNUM(c) ( ASCII_ALPHA(c) || ASCII_DIGIT(c) )
+#define ASCII_PRINTABLE(c) ( (c) >= ' ' && (c) <= '~' )
+
+#define SLAP_NIBBLE(c) ((c)&0x0f)
+#define SLAP_ESCAPE_CHAR ('\\')
+#define SLAP_ESCAPE_LO(c) ( "0123456789ABCDEF"[SLAP_NIBBLE(c)] )
+#define SLAP_ESCAPE_HI(c) ( SLAP_ESCAPE_LO((c)>>4) )
+
+#define FILTER_ESCAPE(c) ( (c) == '*' || (c) == '\\' \
+ || (c) == '(' || (c) == ')' || !ASCII_PRINTABLE(c) )
+
+#define DN_ESCAPE(c) ((c) == SLAP_ESCAPE_CHAR)
+#define DN_SEPARATOR(c) ((c) == ',' || (c) == ';')
+#define RDN_ATTRTYPEANDVALUE_SEPARATOR(c) ((c) == '+') /* RFC 2253 */
+#define RDN_SEPARATOR(c) (DN_SEPARATOR(c) || RDN_ATTRTYPEANDVALUE_SEPARATOR(c))
+#define RDN_NEEDSESCAPE(c) ((c) == '\\' || (c) == '"')
+
+#define DESC_LEADCHAR(c) ( ASCII_ALPHA(c) )
+#define DESC_CHAR(c) ( ASCII_ALNUM(c) || (c) == '-' )
+#define OID_LEADCHAR(c) ( ASCII_DIGIT(c) )
+#define OID_SEPARATOR(c) ( (c) == '.' )
+#define OID_CHAR(c) ( OID_LEADCHAR(c) || OID_SEPARATOR(c) )
+
+#define ATTR_LEADCHAR(c) ( DESC_LEADCHAR(c) || OID_LEADCHAR(c) )
+#define ATTR_CHAR(c) ( DESC_CHAR((c)) || (c) == '.' )
+
+#define AD_LEADCHAR(c) ( ATTR_CHAR(c) )
+#define AD_CHAR(c) ( ATTR_CHAR(c) || (c) == ';' )
+
+#define SLAP_NUMERIC(c) ( ASCII_DIGIT(c) || ASCII_SPACE(c) )
+
+#define SLAP_PRINTABLE(c) ( ASCII_ALNUM(c) || (c) == '\'' || \
+ (c) == '(' || (c) == ')' || (c) == '+' || (c) == ',' || \
+ (c) == '-' || (c) == '.' || (c) == '/' || (c) == ':' || \
+ (c) == '?' || (c) == ' ' || (c) == '=' )
+#define SLAP_PRINTABLES(c) ( SLAP_PRINTABLE(c) || (c) == '$' )
+
+/* must match in schema_init.c */
+#define SLAPD_DN_SYNTAX "1.3.6.1.4.1.1466.115.121.1.12"
+#define SLAPD_NAMEUID_SYNTAX "1.3.6.1.4.1.1466.115.121.1.34"
+#define SLAPD_GROUP_ATTR "member"
+#define SLAPD_GROUP_CLASS "groupOfNames"
+#define SLAPD_ROLE_ATTR "roleOccupant"
+#define SLAPD_ROLE_CLASS "organizationalRole"
+
+#ifdef SLAPD_ACI_ENABLED
+#define SLAPD_ACI_SYNTAX "1.3.6.1.4.1.4203.666.2.1"
+#endif
+
+#define SLAPD_OCTETSTRING_SYNTAX "1.3.6.1.4.1.1466.115.121.1.40"
+
+/* change this to "OpenLDAPset" */
+#define SLAPD_ACI_SET_ATTR "template"
+
+#define SLAPD_TOP_OID "2.5.6.0"
+
+LDAP_SLAPD_V (int) slap_debug;
+
+typedef unsigned long slap_mask_t;
+
+/* Security Strength Factor */
+typedef unsigned slap_ssf_t;
+
+typedef struct slap_ssf_set {
+ slap_ssf_t sss_ssf;
+ slap_ssf_t sss_transport;
+ slap_ssf_t sss_tls;
+ slap_ssf_t sss_sasl;
+ slap_ssf_t sss_update_ssf;
+ slap_ssf_t sss_update_transport;
+ slap_ssf_t sss_update_tls;
+ slap_ssf_t sss_update_sasl;
+} slap_ssf_set_t;
+
+/*
+ * Index types
+ */
+#define SLAP_INDEX_TYPE 0x00FFUL
+#define SLAP_INDEX_UNDEFINED 0x0001UL
+#define SLAP_INDEX_PRESENT 0x0002UL
+#define SLAP_INDEX_EQUALITY 0x0004UL
+#define SLAP_INDEX_APPROX 0x0008UL
+#define SLAP_INDEX_SUBSTR 0x0010UL
+#define SLAP_INDEX_EXTENDED 0x0020UL
+
+#define SLAP_INDEX_DEFAULT SLAP_INDEX_EQUALITY
+
+#define IS_SLAP_INDEX(mask, type) (((mask) & (type)) == (type))
+
+#define SLAP_INDEX_SUBSTR_TYPE 0x0F00UL
+
+#define SLAP_INDEX_SUBSTR_INITIAL ( SLAP_INDEX_SUBSTR | 0x0100UL )
+#define SLAP_INDEX_SUBSTR_ANY ( SLAP_INDEX_SUBSTR | 0x0200UL )
+#define SLAP_INDEX_SUBSTR_FINAL ( SLAP_INDEX_SUBSTR | 0x0400UL )
+#define SLAP_INDEX_SUBSTR_DEFAULT \
+ ( SLAP_INDEX_SUBSTR \
+ | SLAP_INDEX_SUBSTR_INITIAL \
+ | SLAP_INDEX_SUBSTR_ANY \
+ | SLAP_INDEX_SUBSTR_FINAL )
+
+#define SLAP_INDEX_SUBSTR_MINLEN 2
+#define SLAP_INDEX_SUBSTR_MAXLEN 4
+#define SLAP_INDEX_SUBSTR_STEP 2
+
+#define SLAP_INDEX_FLAGS 0xF000UL
+#define SLAP_INDEX_NOSUBTYPES 0x1000UL /* don't use index w/ subtypes */
+#define SLAP_INDEX_NOLANG 0x2000UL /* don't use index w/ lang */
+
+/*
+ * there is a single index for each attribute. these prefixes ensure
+ * that there is no collision among keys.
+ */
+#define SLAP_INDEX_EQUALITY_PREFIX '=' /* prefix for equality keys */
+#define SLAP_INDEX_APPROX_PREFIX '~' /* prefix for approx keys */
+#define SLAP_INDEX_SUBSTR_PREFIX '*' /* prefix for substring keys */
+#define SLAP_INDEX_SUBSTR_INITIAL_PREFIX '^'
+#define SLAP_INDEX_SUBSTR_FINAL_PREFIX '$'
+#define SLAP_INDEX_CONT_PREFIX '.' /* prefix for continuation keys */
+
+#define SLAP_SYNTAX_MATCHINGRULES_OID "1.3.6.1.4.1.1466.115.121.1.30"
+#define SLAP_SYNTAX_ATTRIBUTETYPES_OID "1.3.6.1.4.1.1466.115.121.1.3"
+#define SLAP_SYNTAX_OBJECTCLASSES_OID "1.3.6.1.4.1.1466.115.121.1.37"
+
+/*
+ * represents schema information for a database
+ */
+#define SLAP_SCHERR_OUTOFMEM 1
+#define SLAP_SCHERR_CLASS_NOT_FOUND 2
+#define SLAP_SCHERR_CLASS_BAD_USAGE 3
+#define SLAP_SCHERR_ATTR_NOT_FOUND 4
+#define SLAP_SCHERR_ATTR_BAD_USAGE 5
+#define SLAP_SCHERR_DUP_CLASS 6
+#define SLAP_SCHERR_DUP_ATTR 7
+#define SLAP_SCHERR_DUP_SYNTAX 8
+#define SLAP_SCHERR_DUP_RULE 9
+#define SLAP_SCHERR_NO_NAME 10
+#define SLAP_SCHERR_ATTR_INCOMPLETE 11
+#define SLAP_SCHERR_MR_NOT_FOUND 12
+#define SLAP_SCHERR_SYN_NOT_FOUND 13
+#define SLAP_SCHERR_MR_INCOMPLETE 14
+#define SLAP_SCHERR_NOT_SUPPORTED 15
+#define SLAP_SCHERR_BAD_DESCR 16
+#define SLAP_SCHERR_OIDM 17
+#define SLAP_SCHERR_LAST SLAP_SCHERR_OIDM
+
+typedef union slap_sockaddr {
+ struct sockaddr sa_addr;
+ struct sockaddr_in sa_in_addr;
+#ifdef LDAP_PF_INET6
+ struct sockaddr_in6 sa_in6_addr;
+#endif
+#ifdef LDAP_PF_LOCAL
+ struct sockaddr_un sa_un_addr;
+#endif
+} Sockaddr;
+
+typedef struct slap_oid_macro {
+ struct berval som_oid;
+ char **som_names;
+ struct slap_oid_macro *som_next;
+} OidMacro;
+
+/* forward declarations */
+struct slap_syntax;
+struct slap_matching_rule;
+
+typedef int slap_syntax_validate_func LDAP_P((
+ struct slap_syntax *syntax,
+ struct berval * in));
+
+typedef int slap_syntax_transform_func LDAP_P((
+ struct slap_syntax *syntax,
+ struct berval * in,
+ struct berval * out));
+
+typedef struct slap_syntax {
+ LDAPSyntax ssyn_syn;
+#define ssyn_oid ssyn_syn.syn_oid
+#define ssyn_desc ssyn_syn.syn_desc
+#define ssyn_extensions ssyn_syn.syn_extensions
+ ber_len_t ssyn_oidlen;
+
+ unsigned int ssyn_flags;
+
+#define SLAP_SYNTAX_NONE 0x0000U
+#define SLAP_SYNTAX_BLOB 0x0001U /* syntax treated as blob (audio) */
+#define SLAP_SYNTAX_BINARY 0x0002U /* binary transfer required (certificate) */
+#define SLAP_SYNTAX_BER 0x0004U /* stored in BER encoding (certificate) */
+#define SLAP_SYNTAX_HIDE 0x8000U /* hide (do not publish) */
+
+ slap_syntax_validate_func *ssyn_validate;
+ slap_syntax_transform_func *ssyn_normalize;
+ slap_syntax_transform_func *ssyn_pretty;
+
+#ifdef SLAPD_BINARY_CONVERSION
+ /* convert to and from binary */
+ slap_syntax_transform_func *ssyn_ber2str;
+ slap_syntax_transform_func *ssyn_str2ber;
+#endif
+
+ struct slap_syntax *ssyn_next;
+} Syntax;
+
+#define slap_syntax_is_flag(s,flag) ((int)((s)->ssyn_flags & (flag)) ? 1 : 0)
+#define slap_syntax_is_blob(s) slap_syntax_is_flag((s),SLAP_SYNTAX_BLOB)
+#define slap_syntax_is_binary(s) slap_syntax_is_flag((s),SLAP_SYNTAX_BINARY)
+#define slap_syntax_is_ber(s) slap_syntax_is_flag((s),SLAP_SYNTAX_BER)
+#define slap_syntax_is_hidden(s) slap_syntax_is_flag((s),SLAP_SYNTAX_HIDE)
+
+/* X -> Y Converter */
+typedef int slap_mr_convert_func LDAP_P((
+ struct berval * in,
+ struct berval * out ));
+
+/* Normalizer */
+typedef int slap_mr_normalize_func LDAP_P((
+ slap_mask_t use,
+ struct slap_syntax *syntax, /* NULL if in is asserted value */
+ struct slap_matching_rule *mr,
+ struct berval * in,
+ struct berval * out ));
+
+/* Match (compare) function */
+typedef int slap_mr_match_func LDAP_P((
+ int *match,
+ slap_mask_t use,
+ struct slap_syntax *syntax, /* syntax of stored value */
+ struct slap_matching_rule *mr,
+ struct berval * value,
+ void * assertValue ));
+
+/* Index generation function */
+typedef int slap_mr_indexer_func LDAP_P((
+ slap_mask_t use,
+ slap_mask_t mask,
+ struct slap_syntax *syntax, /* syntax of stored value */
+ struct slap_matching_rule *mr,
+ struct berval *prefix,
+ BerVarray values,
+ BerVarray *keys ));
+
+/* Filter index function */
+typedef int slap_mr_filter_func LDAP_P((
+ slap_mask_t use,
+ slap_mask_t mask,
+ struct slap_syntax *syntax, /* syntax of stored value */
+ struct slap_matching_rule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ BerVarray *keys ));
+
+typedef struct slap_matching_rule {
+ LDAPMatchingRule smr_mrule;
+ ber_len_t smr_oidlen;
+ slap_mask_t smr_usage;
+
+#define SLAP_MR_HIDE 0x8000U
+
+#define SLAP_MR_TYPE_MASK 0x0F00U
+#define SLAP_MR_SUBTYPE_MASK 0x00F0U
+#define SLAP_MR_USAGE 0x000FU
+
+#define SLAP_MR_NONE 0x0000U
+#define SLAP_MR_EQUALITY 0x0100U
+#define SLAP_MR_ORDERING 0x0200U
+#define SLAP_MR_SUBSTR 0x0400U
+#define SLAP_MR_EXT 0x0800U
+
+#define SLAP_MR_EQUALITY_APPROX ( SLAP_MR_EQUALITY | 0x0010U )
+#define SLAP_MR_DN_FOLD 0x0008U
+
+#define SLAP_MR_SUBSTR_INITIAL ( SLAP_MR_SUBSTR | 0x0010U )
+#define SLAP_MR_SUBSTR_ANY ( SLAP_MR_SUBSTR | 0x0020U )
+#define SLAP_MR_SUBSTR_FINAL ( SLAP_MR_SUBSTR | 0x0040U )
+
+/*
+ * normally the provided value is expected to conform to
+ * assertion syntax specified in the matching rule, however
+ * at times (such as during individual value modification),
+ * the provided value is expected to conform to the
+ * attribute's value syntax.
+ */
+#define SLAP_MR_ASSERTION_SYNTAX_MATCH 0x0000U
+#define SLAP_MR_VALUE_SYNTAX_MATCH 0x0001U
+#define SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH 0x0003U
+
+#define SLAP_IS_MR_ASSERTION_SYNTAX_MATCH( usage ) \
+ (!((usage) & SLAP_MR_VALUE_SYNTAX_MATCH))
+#define SLAP_IS_MR_VALUE_SYNTAX_MATCH( usage ) \
+ ((usage) & SLAP_MR_VALUE_SYNTAX_MATCH)
+
+#define SLAP_IS_MR_VALUE_SYNTAX_CONVERTED_MATCH( usage ) \
+ (((usage) & SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH) \
+ == SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH)
+#define SLAP_IS_MR_VALUE_SYNTAX_NONCONVERTED_MATCH( usage ) \
+ (((usage) & SLAP_MR_VALUE_SYNTAX_CONVERTED_MATCH) \
+ == SLAP_MR_VALUE_SYNTAX_MATCH)
+
+ Syntax *smr_syntax;
+ slap_mr_convert_func *smr_convert;
+ slap_mr_normalize_func *smr_normalize;
+ slap_mr_match_func *smr_match;
+ slap_mr_indexer_func *smr_indexer;
+ slap_mr_filter_func *smr_filter;
+
+ struct slap_matching_rule *smr_associated;
+ struct slap_matching_rule *smr_next;
+
+#define smr_oid smr_mrule.mr_oid
+#define smr_names smr_mrule.mr_names
+#define smr_desc smr_mrule.mr_desc
+#define smr_obsolete smr_mrule.mr_obsolete
+#define smr_syntax_oid smr_mrule.mr_syntax_oid
+#define smr_extensions smr_mrule.mr_extensions
+} MatchingRule;
+
+struct slap_backend_db;
+struct slap_entry;
+struct slap_attr;
+
+typedef int (AttributeTypeSchemaCheckFN)(
+ struct slap_backend_db *be,
+ struct slap_entry *e,
+ struct slap_attr *attr,
+ const char** text,
+ char *textbuf, size_t textlen );
+
+typedef struct slap_attribute_type {
+ LDAPAttributeType sat_atype;
+ struct berval sat_cname;
+ struct slap_attribute_type *sat_sup;
+ struct slap_attribute_type **sat_subtypes;
+ MatchingRule *sat_equality;
+ MatchingRule *sat_approx;
+ MatchingRule *sat_ordering;
+ MatchingRule *sat_substr;
+ Syntax *sat_syntax;
+
+ AttributeTypeSchemaCheckFN *sat_check;
+ slap_mask_t sat_flags;
+
+ struct slap_attribute_type *sat_next;
+
+#define sat_oid sat_atype.at_oid
+#define sat_names sat_atype.at_names
+#define sat_desc sat_atype.at_desc
+#define sat_obsolete sat_atype.at_obsolete
+#define sat_sup_oid sat_atype.at_sup_oid
+#define sat_equality_oid sat_atype.at_equality_oid
+#define sat_ordering_oid sat_atype.at_ordering_oid
+#define sat_substr_oid sat_atype.at_substr_oid
+#define sat_syntax_oid sat_atype.at_syntax_oid
+#define sat_single_value sat_atype.at_single_value
+#define sat_collective sat_atype.at_collective
+#define sat_no_user_mod sat_atype.at_no_user_mod
+#define sat_usage sat_atype.at_usage
+#define sat_extensions sat_atype.at_extensions
+
+ struct slap_attr_desc *sat_ad;
+ ldap_pvt_thread_mutex_t sat_ad_mutex;
+} AttributeType;
+
+#define is_at_operational(at) ((at)->sat_usage)
+#define is_at_single_value(at) ((at)->sat_single_value)
+#define is_at_collective(at) ((at)->sat_collective)
+#define is_at_obsolete(at) ((at)->sat_obsolete)
+#define is_at_no_user_mod(at) ((at)->sat_no_user_mod)
+
+struct slap_object_class;
+
+typedef int (ObjectClassSchemaCheckFN)(
+ struct slap_backend_db *be,
+ struct slap_entry *e,
+ struct slap_object_class *oc,
+ const char** text,
+ char *textbuf, size_t textlen );
+
+typedef struct slap_object_class {
+ LDAPObjectClass soc_oclass;
+ struct slap_object_class **soc_sups;
+ AttributeType **soc_required;
+ AttributeType **soc_allowed;
+ ObjectClassSchemaCheckFN *soc_check;
+ slap_mask_t soc_flags;
+#define soc_oid soc_oclass.oc_oid
+#define soc_names soc_oclass.oc_names
+#define soc_desc soc_oclass.oc_desc
+#define soc_obsolete soc_oclass.oc_obsolete
+#define soc_sup_oids soc_oclass.oc_sup_oids
+#define soc_kind soc_oclass.oc_kind
+#define soc_at_oids_must soc_oclass.oc_at_oids_must
+#define soc_at_oids_may soc_oclass.oc_at_oids_may
+#define soc_extensions soc_oclass.oc_extensions
+
+ struct slap_object_class *soc_next;
+} ObjectClass;
+
+#define SLAP_OC_ALIAS 0x01
+#define SLAP_OC_REFERRAL 0x02
+#define SLAP_OC_SUBENTRY 0x04
+#define SLAP_OC_DYNAMICOBJECT 0x08
+#define SLAP_OC_COLLECTIVEATTRIBUTESUBENTRY 0x10
+#define SLAP_OC__MASK 0x1F
+#define SLAP_OC__END 0x20
+
+#ifdef LDAP_EXTENDED_SCHEMA
+/*
+ * DIT content rule
+ */
+typedef struct slap_content_rule {
+ LDAPContentRule scr_crule;
+ ObjectClass *scr_sclass;
+ ObjectClass **scr_auxiliaries; /* optional */
+ AttributeType **scr_required; /* optional */
+ AttributeType **scr_allowed; /* optional */
+ AttributeType **scr_precluded; /* optional */
+#define scr_oid scr_crule.cr_oid
+#define scr_names scr_crule.cr_names
+#define scr_desc scr_crule.cr_desc
+#define scr_obsolete soc_oclass.cr_obsolete
+#define scr_cr_oids_aux soc_oclass.cr_oc_oids_aux
+#define scr_cr_oids_must soc_oclass.cr_at_oids_must
+#define scr_cr_oids_may soc_oclass.cr_at_oids_may
+#define scr_cr_oids_not soc_oclass.cr_at_oids_not
+} ContentRule;
+#endif
+
+/*
+ * represents a recognized attribute description ( type + options )
+ */
+typedef struct slap_attr_desc {
+ struct slap_attr_desc *ad_next;
+ AttributeType *ad_type; /* attribute type, must be specified */
+ struct berval ad_cname; /* canonical name, must be specified */
+ struct berval ad_lang; /* empty if no language tags */
+ unsigned ad_flags;
+#define SLAP_DESC_NONE 0x00U
+#define SLAP_DESC_BINARY 0x01U
+#define SLAP_DESC_LANG_RANGE 0x80U
+} AttributeDescription;
+
+typedef struct slap_attr_name {
+ struct berval an_name;
+ AttributeDescription *an_desc;
+ ObjectClass *an_oc;
+} AttributeName;
+
+#define slap_ad_is_lang(ad) ( (ad)->ad_lang.bv_len != 0 )
+#define slap_ad_is_lang_range(ad) \
+ ( ((ad)->ad_flags & SLAP_DESC_LANG_RANGE) ? 1 : 0 )
+#define slap_ad_is_binary(ad) \
+ ( ((ad)->ad_flags & SLAP_DESC_BINARY) ? 1 : 0 )
+
+/*
+ * pointers to schema elements used internally
+ */
+struct slap_internal_schema {
+ /* objectClass */
+ ObjectClass *si_oc_top;
+ ObjectClass *si_oc_extensibleObject;
+ ObjectClass *si_oc_alias;
+ ObjectClass *si_oc_referral;
+ ObjectClass *si_oc_rootdse;
+ ObjectClass *si_oc_subentry;
+ ObjectClass *si_oc_subschema;
+ ObjectClass *si_oc_monitor;
+ ObjectClass *si_oc_collectiveAttributeSubentry;
+ ObjectClass *si_oc_dynamicObject;
+
+ /* objectClass attribute descriptions */
+ AttributeDescription *si_ad_objectClass;
+
+ /* operational attribute descriptions */
+ AttributeDescription *si_ad_structuralObjectClass;
+ AttributeDescription *si_ad_creatorsName;
+ AttributeDescription *si_ad_createTimestamp;
+ AttributeDescription *si_ad_modifiersName;
+ AttributeDescription *si_ad_modifyTimestamp;
+ AttributeDescription *si_ad_hasSubordinates;
+ AttributeDescription *si_ad_subschemaSubentry;
+ AttributeDescription *si_ad_collectiveSubentries;
+ AttributeDescription *si_ad_collectiveExclusions;
+ AttributeDescription *si_ad_entryUUID;
+ AttributeDescription *si_ad_entryCSN;
+
+ /* root DSE attribute descriptions */
+ AttributeDescription *si_ad_altServer;
+ AttributeDescription *si_ad_namingContexts;
+ AttributeDescription *si_ad_supportedControl;
+ AttributeDescription *si_ad_supportedExtension;
+ AttributeDescription *si_ad_supportedLDAPVersion;
+ AttributeDescription *si_ad_supportedSASLMechanisms;
+ AttributeDescription *si_ad_supportedFeatures;
+ AttributeDescription *si_ad_vendorName;
+ AttributeDescription *si_ad_vendorVersion;
+
+ /* subentry attribute descriptions */
+ AttributeDescription *si_ad_administrativeRole;
+ AttributeDescription *si_ad_subtreeSpecification;
+
+ /* subschema subentry attribute descriptions */
+ AttributeDescription *si_ad_ditStructureRules;
+ AttributeDescription *si_ad_ditContentRules;
+ AttributeDescription *si_ad_nameForms;
+ AttributeDescription *si_ad_objectClasses;
+ AttributeDescription *si_ad_attributeTypes;
+ AttributeDescription *si_ad_ldapSyntaxes;
+ AttributeDescription *si_ad_matchingRules;
+ AttributeDescription *si_ad_matchingRuleUse;
+
+ /* Aliases & Referrals */
+ AttributeDescription *si_ad_aliasedObjectName;
+ AttributeDescription *si_ad_ref;
+
+ /* Access Control Internals */
+ AttributeDescription *si_ad_entry;
+ AttributeDescription *si_ad_children;
+#ifdef SLAPD_ACI_ENABLED
+ AttributeDescription *si_ad_aci;
+#endif
+
+ /* dynamic entries */
+ AttributeDescription *si_ad_entryTtl;
+ AttributeDescription *si_ad_dynamicSubtrees;
+
+ /* Other attributes descriptions */
+ AttributeDescription *si_ad_distinguishedName;
+ AttributeDescription *si_ad_name;
+ AttributeDescription *si_ad_cn;
+ AttributeDescription *si_ad_userPassword;
+#ifdef SLAPD_AUTHPASSWD
+ AttributeDescription *si_ad_authPassword;
+#endif
+#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
+ AttributeDescription *si_ad_krbName;
+#endif
+
+ /* Undefined Attribute Type */
+ AttributeType *si_at_undefined;
+
+ /* Matching Rules */
+ MatchingRule *si_mr_distinguishedNameMatch;
+ MatchingRule *si_mr_integerMatch;
+
+ /* Syntaxes */
+ Syntax *si_syn_distinguishedName;
+ Syntax *si_syn_integer;
+};
+
+typedef struct slap_attr_assertion {
+ AttributeDescription *aa_desc;
+ struct berval aa_value;
+} AttributeAssertion;
+
+typedef struct slap_ss_assertion {
+ AttributeDescription *sa_desc;
+ struct berval sa_initial;
+ struct berval *sa_any;
+ struct berval sa_final;
+} SubstringsAssertion;
+
+typedef struct slap_mr_assertion {
+ MatchingRule *ma_rule; /* optional */
+ struct berval ma_rule_text; /* optional */
+ AttributeDescription *ma_desc; /* optional */
+ int ma_dnattrs; /* boolean */
+ struct berval ma_value; /* required */
+} MatchingRuleAssertion;
/*
* represents a search filter
*/
-typedef struct filter {
- unsigned long f_choice; /* values taken from ldap.h */
+typedef struct slap_filter {
+ ber_tag_t f_choice; /* values taken from ldap.h, plus: */
+#define SLAPD_FILTER_COMPUTED ((ber_tag_t) -1)
+#define SLAPD_FILTER_DN_ONE ((ber_tag_t) -2)
+#define SLAPD_FILTER_DN_SUBTREE ((ber_tag_t) -3)
+
+ union f_un_u {
+ /* precomputed result */
+ ber_int_t f_un_result;
+
+ /* DN */
+ struct berval *f_un_dn;
- union {
/* present */
- char *f_un_type;
+ AttributeDescription *f_un_desc;
+
+ /* simple value assertion */
+ AttributeAssertion *f_un_ava;
- /* equality, lessorequal, greaterorequal, approx */
- Ava f_un_ava;
+ /* substring assertion */
+ SubstringsAssertion *f_un_ssa;
+
+ /* matching rule assertion */
+ MatchingRuleAssertion *f_un_mra;
+
+#define f_dn f_un.f_un_dn
+#define f_desc f_un.f_un_desc
+#define f_ava f_un.f_un_ava
+#define f_av_desc f_un.f_un_ava->aa_desc
+#define f_av_value f_un.f_un_ava->aa_value
+#define f_sub f_un.f_un_ssa
+#define f_sub_desc f_un.f_un_ssa->sa_desc
+#define f_sub_initial f_un.f_un_ssa->sa_initial
+#define f_sub_any f_un.f_un_ssa->sa_any
+#define f_sub_final f_un.f_un_ssa->sa_final
+#define f_mra f_un.f_un_mra
+#define f_mr_rule f_un.f_un_mra->ma_rule
+#define f_mr_rule_text f_un.f_un_mra->ma_rule_text
+#define f_mr_desc f_un.f_un_mra->ma_desc
+#define f_mr_value f_un.f_un_mra->ma_value
+#define f_mr_dnattrs f_un.f_un_mra->ma_dnattrs
/* and, or, not */
- struct filter *f_un_complex;
-
- /* substrings */
- struct sub {
- char *f_un_sub_type;
- char *f_un_sub_initial;
- char **f_un_sub_any;
- char *f_un_sub_final;
- } f_un_sub;
+ struct slap_filter *f_un_complex;
} f_un;
-#define f_type f_un.f_un_type
-#define f_ava f_un.f_un_ava
-#define f_avtype f_un.f_un_ava.ava_type
-#define f_avvalue f_un.f_un_ava.ava_value
+
+#define f_result f_un.f_un_result
#define f_and f_un.f_un_complex
#define f_or f_un.f_un_complex
#define f_not f_un.f_un_complex
#define f_list f_un.f_un_complex
-#define f_sub f_un.f_un_sub
-#define f_sub_type f_un.f_un_sub.f_un_sub_type
-#define f_sub_initial f_un.f_un_sub.f_un_sub_initial
-#define f_sub_any f_un.f_un_sub.f_un_sub_any
-#define f_sub_final f_un.f_un_sub.f_un_sub_final
- struct filter *f_next;
+ struct slap_filter *f_next;
} Filter;
+/* compare routines can return undefined */
+#define SLAPD_COMPARE_UNDEFINED ((ber_int_t) -1)
+
/*
- * represents an attribute (type + values + syntax)
+ * represents an attribute (description + values)
*/
-typedef struct attr {
- char *a_type;
- struct berval **a_vals;
- int a_syntax;
- struct attr *a_next;
+typedef struct slap_attr {
+ AttributeDescription *a_desc;
+ BerVarray a_vals;
+ struct slap_attr *a_next;
+ unsigned a_flags;
+#define SLAP_ATTR_IXADD 0x1U
+#define SLAP_ATTR_IXDEL 0x2U
} Attribute;
-/*
- * the attr_syntax() routine returns one of these values
- * telling what kind of syntax an attribute supports.
- */
-#define SYNTAX_CIS 0x01 /* case insensitive string */
-#define SYNTAX_CES 0x02 /* case sensitive string */
-#define SYNTAX_BIN 0x04 /* binary data */
-#define SYNTAX_TEL 0x08 /* telephone number string */
-#define SYNTAX_DN 0x10 /* dn string */
/*
* the id used in the indexes to refer to an entry
*/
typedef unsigned long ID;
-#define NOID ((unsigned long)-1)
+#define NOID ((ID)~0)
/*
* represents an entry in core
*/
-typedef struct entry {
- char *e_dn; /* DN of this entry */
- Attribute *e_attrs; /* list of attributes + values */
-
- ID e_id; /* id of this entry - this should */
- /* really be private to back-ldbm */
- char e_state; /* for the cache */
-#define ENTRY_STATE_DELETED 1
-#define ENTRY_STATE_CREATING 2
- int e_refcnt; /* # threads ref'ing this entry */
- struct entry *e_lrunext; /* for cache lru list */
- struct entry *e_lruprev;
+typedef struct slap_entry {
+ /*
+ * The ID field should only be changed before entry is
+ * inserted into a cache. The ID value is backend
+ * specific.
+ */
+ ID e_id;
+
+ struct berval e_name; /* name (DN) of this entry */
+ struct berval e_nname; /* normalized name (DN) of this entry */
+
+ /* for migration purposes */
+#define e_dn e_name.bv_val
+#define e_ndn e_nname.bv_val
+
+ Attribute *e_attrs; /* list of attributes + values */
+
+ slap_mask_t e_ocflags;
+
+ struct berval e_bv; /* For entry_encode/entry_decode */
+
+ /* for use by the backend for any purpose */
+ void* e_private;
} Entry;
+/*
+ * A list of LDAPMods
+ */
+typedef struct slap_mod {
+ int sm_op;
+ AttributeDescription *sm_desc;
+ struct berval sm_type;
+ BerVarray sm_bvalues;
+} Modification;
+
+typedef struct slap_mod_list {
+ Modification sml_mod;
+#define sml_op sml_mod.sm_op
+#define sml_desc sml_mod.sm_desc
+#define sml_type sml_mod.sm_type
+#define sml_bvalues sml_mod.sm_bvalues
+ struct slap_mod_list *sml_next;
+} Modifications;
+
+typedef struct slap_ldap_modlist {
+ LDAPMod ml_mod;
+ struct slap_ldap_modlist *ml_next;
+#define ml_op ml_mod.mod_op
+#define ml_type ml_mod.mod_type
+#define ml_values ml_mod.mod_values
+#define ml_bvalues ml_mod.mod_bvalues
+} LDAPModList;
+
/*
* represents an access control list
*/
+typedef enum slap_access_e {
+ ACL_INVALID_ACCESS = -1,
+ ACL_NONE = 0,
+ ACL_AUTH,
+ ACL_COMPARE,
+ ACL_SEARCH,
+ ACL_READ,
+ ACL_WRITE
+} slap_access_t;
+
+typedef enum slap_control_e {
+ ACL_INVALID_CONTROL = 0,
+ ACL_STOP,
+ ACL_CONTINUE,
+ ACL_BREAK
+} slap_control_t;
+
+typedef enum slap_style_e {
+ ACL_STYLE_REGEX = 0,
+ ACL_STYLE_BASE,
+ ACL_STYLE_ONE,
+ ACL_STYLE_SUBTREE,
+ ACL_STYLE_CHILDREN,
+ ACL_STYLE_ATTROF,
+
+ /* alternate names */
+ ACL_STYLE_EXACT = ACL_STYLE_BASE
+} slap_style_t;
+
+typedef struct slap_authz_info {
+ ber_tag_t sai_method; /* LDAP_AUTH_* from <ldap.h> */
+ struct berval sai_mech; /* SASL Mechanism */
+ struct berval sai_dn; /* DN for reporting purposes */
+ struct berval sai_ndn; /* Normalized DN */
+
+ /* Security Strength Factors */
+ slap_ssf_t sai_ssf; /* Overall SSF */
+ slap_ssf_t sai_transport_ssf; /* Transport SSF */
+ slap_ssf_t sai_tls_ssf; /* TLS SSF */
+ slap_ssf_t sai_sasl_ssf; /* SASL SSF */
+} AuthorizationInformation;
/* the "by" part */
-struct access {
- char *a_dnpat;
- char *a_addrpat;
- char *a_domainpat;
- char *a_dnattr;
- long a_access;
-#define ACL_NONE 0x01
-#define ACL_COMPARE 0x02
-#define ACL_SEARCH 0x04
-#define ACL_READ 0x08
-#define ACL_WRITE 0x10
-#define ACL_SELF 0x40
- struct access *a_next;
-};
+typedef struct slap_access {
+ slap_control_t a_type;
+
+#define ACL_ACCESS2PRIV(access) (0x01U << (access))
+
+#define ACL_PRIV_NONE ACL_ACCESS2PRIV( ACL_NONE )
+#define ACL_PRIV_AUTH ACL_ACCESS2PRIV( ACL_AUTH )
+#define ACL_PRIV_COMPARE ACL_ACCESS2PRIV( ACL_COMPARE )
+#define ACL_PRIV_SEARCH ACL_ACCESS2PRIV( ACL_SEARCH )
+#define ACL_PRIV_READ ACL_ACCESS2PRIV( ACL_READ )
+#define ACL_PRIV_WRITE ACL_ACCESS2PRIV( ACL_WRITE )
+
+#define ACL_PRIV_MASK 0x00ffUL
+
+/* priv flags */
+#define ACL_PRIV_LEVEL 0x1000UL
+#define ACL_PRIV_ADDITIVE 0x2000UL
+#define ACL_PRIV_SUBSTRACTIVE 0x4000UL
+
+/* invalid privs */
+#define ACL_PRIV_INVALID 0x0UL
+
+#define ACL_PRIV_ISSET(m,p) (((m) & (p)) == (p))
+#define ACL_PRIV_ASSIGN(m,p) do { (m) = (p); } while(0)
+#define ACL_PRIV_SET(m,p) do { (m) |= (p); } while(0)
+#define ACL_PRIV_CLR(m,p) do { (m) &= ~(p); } while(0)
+
+#define ACL_INIT(m) ACL_PRIV_ASSIGN(m, ACL_PRIV_NONE)
+#define ACL_INVALIDATE(m) ACL_PRIV_ASSIGN(m, ACL_PRIV_INVALID)
+
+#define ACL_GRANT(m,a) ACL_PRIV_ISSET((m),ACL_ACCESS2PRIV(a))
+
+#define ACL_IS_INVALID(m) ((m) == ACL_PRIV_INVALID)
+
+#define ACL_IS_LEVEL(m) ACL_PRIV_ISSET((m),ACL_PRIV_LEVEL)
+#define ACL_IS_ADDITIVE(m) ACL_PRIV_ISSET((m),ACL_PRIV_ADDITIVE)
+#define ACL_IS_SUBTRACTIVE(m) ACL_PRIV_ISSET((m),ACL_PRIV_SUBSTRACTIVE)
+
+#define ACL_LVL_NONE (ACL_PRIV_NONE|ACL_PRIV_LEVEL)
+#define ACL_LVL_AUTH (ACL_PRIV_AUTH|ACL_LVL_NONE)
+#define ACL_LVL_COMPARE (ACL_PRIV_COMPARE|ACL_LVL_AUTH)
+#define ACL_LVL_SEARCH (ACL_PRIV_SEARCH|ACL_LVL_COMPARE)
+#define ACL_LVL_READ (ACL_PRIV_READ|ACL_LVL_SEARCH)
+#define ACL_LVL_WRITE (ACL_PRIV_WRITE|ACL_LVL_READ)
+
+#define ACL_LVL(m,l) (((m)&ACL_PRIV_MASK) == ((l)&ACL_PRIV_MASK))
+#define ACL_LVL_IS_NONE(m) ACL_LVL((m),ACL_LVL_NONE)
+#define ACL_LVL_IS_AUTH(m) ACL_LVL((m),ACL_LVL_AUTH)
+#define ACL_LVL_IS_COMPARE(m) ACL_LVL((m),ACL_LVL_COMPARE)
+#define ACL_LVL_IS_SEARCH(m) ACL_LVL((m),ACL_LVL_SEARCH)
+#define ACL_LVL_IS_READ(m) ACL_LVL((m),ACL_LVL_READ)
+#define ACL_LVL_IS_WRITE(m) ACL_LVL((m),ACL_LVL_WRITE)
+
+#define ACL_LVL_ASSIGN_NONE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_NONE)
+#define ACL_LVL_ASSIGN_AUTH(m) ACL_PRIV_ASSIGN((m),ACL_LVL_AUTH)
+#define ACL_LVL_ASSIGN_COMPARE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_COMPARE)
+#define ACL_LVL_ASSIGN_SEARCH(m) ACL_PRIV_ASSIGN((m),ACL_LVL_SEARCH)
+#define ACL_LVL_ASSIGN_READ(m) ACL_PRIV_ASSIGN((m),ACL_LVL_READ)
+#define ACL_LVL_ASSIGN_WRITE(m) ACL_PRIV_ASSIGN((m),ACL_LVL_WRITE)
+
+ slap_mask_t a_access_mask;
+
+ AuthorizationInformation a_authz;
+#define a_dn_pat a_authz.sai_dn
+
+ slap_style_t a_dn_style;
+ AttributeDescription *a_dn_at;
+ int a_dn_self;
+
+ slap_style_t a_peername_style;
+ struct berval a_peername_pat;
+ slap_style_t a_sockname_style;
+ struct berval a_sockname_pat;
+
+ slap_style_t a_domain_style;
+ struct berval a_domain_pat;
+ slap_style_t a_sockurl_style;
+ struct berval a_sockurl_pat;
+ slap_style_t a_set_style;
+ struct berval a_set_pat;
+
+#ifdef SLAPD_ACI_ENABLED
+ AttributeDescription *a_aci_at;
+#endif
+
+ /* ACL Groups */
+ slap_style_t a_group_style;
+ struct berval a_group_pat;
+ ObjectClass *a_group_oc;
+ AttributeDescription *a_group_at;
+
+ struct slap_access *a_next;
+} Access;
/* the "to" part */
-struct acl {
+typedef struct slap_acl {
/* "to" part: the entries this acl applies to */
Filter *acl_filter;
- char *acl_dnpat;
- char **acl_attrs;
+ slap_style_t acl_dn_style;
+ regex_t acl_dn_re;
+ struct berval acl_dn_pat;
+ AttributeName *acl_attrs;
/* "by" part: list of who has what access to the entries */
- struct access *acl_access;
+ Access *acl_access;
- struct acl *acl_next;
-};
+ struct slap_acl *acl_next;
+} AccessControl;
+
+typedef struct slap_acl_state {
+ unsigned as_recorded;
+#define ACL_STATE_NOT_RECORDED 0x0
+#define ACL_STATE_RECORDED_VD 0x1
+#define ACL_STATE_RECORDED_NV 0x2
+#define ACL_STATE_RECORDED 0x3
+
+ /* Access state */
+ AccessControl *as_vd_acl;
+ slap_mask_t as_vd_acl_mask;
+ regmatch_t as_vd_acl_matches[MAXREMATCHES];
+ int as_vd_acl_count;
+
+ Access *as_vd_access;
+ int as_vd_access_count;
+
+ int as_result;
+} AccessControlState;
+#define ACL_STATE_INIT { ACL_STATE_NOT_RECORDED, NULL, 0UL, { 0 }, 0, NULL, 0 }
/*
- * represents schema information for a database
+ * replog moddn param structure
*/
-
-struct objclass {
- char *oc_name;
- char **oc_required;
- char **oc_allowed;
- struct objclass *oc_next;
+struct slap_replog_moddn {
+ struct berval *newrdn;
+ int deloldrdn;
+ struct berval *newsup;
};
/*
- * represents a "database"
+ * Backend-info
+ * represents a backend
*/
-typedef struct backend {
- char **be_suffix; /* the DN suffixes of data in this backend */
- char *be_rootdn; /* the magic "root" dn for this db */
- char *be_rootpw; /* the magic "root" password for this db */
- int be_readonly; /* 1 => db is in "read only" mode */
- int be_sizelimit; /* size limit for this backend */
- int be_timelimit; /* time limit for this backend */
- struct acl *be_acl; /* access control list for this backend */
- int be_dfltaccess; /* access given if no acl matches */
- char **be_replica; /* replicas of this backend (in master) */
+typedef struct slap_backend_info BackendInfo; /* per backend type */
+typedef struct slap_backend_db BackendDB; /* per backend database */
+
+LDAP_SLAPD_V (int) nBackendInfo;
+LDAP_SLAPD_V (int) nBackendDB;
+LDAP_SLAPD_V (BackendInfo *) backendInfo;
+LDAP_SLAPD_V (BackendDB *) backendDB;
+
+LDAP_SLAPD_V (int) slapMode;
+#define SLAP_UNDEFINED_MODE 0x0000
+#define SLAP_SERVER_MODE 0x0001
+#define SLAP_TOOL_MODE 0x0002
+#define SLAP_MODE 0x0003
+
+#define SLAP_TRUNCATE_MODE 0x0100
+
+struct slap_replica_info {
+ char *ri_host; /* supersedes be_replica */
+ struct berval **ri_nsuffix; /* array of suffixes this replica accepts */
+ AttributeName *ri_attrs; /* attrs to replicate, NULL=all */
+};
+
+struct slap_limits_set {
+ /* time limits */
+ int lms_t_soft;
+ int lms_t_hard;
+
+ /* size limits */
+ int lms_s_soft;
+ int lms_s_hard;
+ int lms_s_unchecked;
+};
+
+struct slap_limits {
+ int lm_type; /* type of pattern */
+#define SLAP_LIMITS_UNDEFINED 0x0000
+#define SLAP_LIMITS_EXACT 0x0001
+#define SLAP_LIMITS_BASE SLAP_LIMITS_EXACT
+#define SLAP_LIMITS_ONE 0x0002
+#define SLAP_LIMITS_SUBTREE 0x0003
+#define SLAP_LIMITS_CHILDREN 0x0004
+#define SLAP_LIMITS_REGEX 0x0005
+#define SLAP_LIMITS_ANONYMOUS 0x0006
+#define SLAP_LIMITS_USERS 0x0007
+ regex_t lm_dn_regex; /* regex data for REGEX */
+
+ /*
+ * normalized DN for EXACT, BASE, ONE, SUBTREE, CHILDREN;
+ * pattern for REGEX; NULL for ANONYMOUS, USERS
+ */
+ struct berval lm_dn_pat;
+
+ struct slap_limits_set lm_limits;
+};
+
+/* temporary aliases */
+typedef BackendDB Backend;
+#define nbackends nBackendDB
+#define backends backendDB
+
+struct slap_backend_db {
+ BackendInfo *bd_info; /* pointer to shared backend info */
+
+ /* BackendInfo accessors */
+#define be_config bd_info->bi_db_config
+#define be_type bd_info->bi_type
+
+#define be_bind bd_info->bi_op_bind
+#define be_unbind bd_info->bi_op_unbind
+#define be_add bd_info->bi_op_add
+#define be_compare bd_info->bi_op_compare
+#define be_delete bd_info->bi_op_delete
+#define be_modify bd_info->bi_op_modify
+#define be_modrdn bd_info->bi_op_modrdn
+#define be_search bd_info->bi_op_search
+
+#define be_extended bd_info->bi_extended
+
+#define be_release bd_info->bi_entry_release_rw
+#define be_chk_referrals bd_info->bi_chk_referrals
+#define be_group bd_info->bi_acl_group
+#define be_attribute bd_info->bi_acl_attribute
+#define be_operational bd_info->bi_operational
+
+#define be_controls bd_info->bi_controls
+
+#define be_connection_init bd_info->bi_connection_init
+#define be_connection_destroy bd_info->bi_connection_destroy
+
+#ifdef SLAPD_TOOLS
+#define be_entry_open bd_info->bi_tool_entry_open
+#define be_entry_close bd_info->bi_tool_entry_close
+#define be_entry_first bd_info->bi_tool_entry_first
+#define be_entry_next bd_info->bi_tool_entry_next
+#define be_entry_reindex bd_info->bi_tool_entry_reindex
+#define be_entry_get bd_info->bi_tool_entry_get
+#define be_entry_put bd_info->bi_tool_entry_put
+#define be_sync bd_info->bi_tool_sync
+#endif
+
+#define SLAP_BFLAG_NOLASTMOD 0x0001U
+#define SLAP_BFLAG_GLUE_INSTANCE 0x0010U /* a glue backend */
+#define SLAP_BFLAG_GLUE_SUBORDINATE 0x0020U /* child of a glue hierarchy */
+#define SLAP_BFLAG_GLUE_LINKED 0x0040U /* child is connected to parent */
+#define SLAP_BFLAG_ALIASES 0x0100U
+#define SLAP_BFLAG_REFERRALS 0x0200U
+#define SLAP_BFLAG_SUBENTRIES 0x0400U
+#define SLAP_BFLAG_MONITOR 0x1000U
+#define SLAP_BFLAG_DYNAMIC 0x2000U
+ slap_mask_t be_flags;
+#define SLAP_LASTMOD(be) (!((be)->be_flags & SLAP_BFLAG_NOLASTMOD))
+#define SLAP_ALIASES(be) ((be)->be_flags & SLAP_BFLAG_ALIASES)
+#define SLAP_REFERRALS(be) ((be)->be_flags & SLAP_BFLAG_REFERRALS)
+#define SLAP_SUBENTRIES(be) ((be)->be_flags & SLAP_BFLAG_SUBENTRIES)
+#define SLAP_MONITOR(be) ((be)->be_flags & SLAP_BFLAG_MONITOR)
+#define SLAP_DYNAMIC(be) ((be)->be_flags & SLAP_BFLAG_DYNAMIC)
+
+ slap_mask_t be_restrictops; /* restriction operations */
+#define SLAP_RESTRICT_OP_ADD 0x0001U
+#define SLAP_RESTRICT_OP_BIND 0x0002U
+#define SLAP_RESTRICT_OP_COMPARE 0x0004U
+#define SLAP_RESTRICT_OP_DELETE 0x0008U
+#define SLAP_RESTRICT_OP_EXTENDED 0x0010U
+#define SLAP_RESTRICT_OP_MODIFY 0x0020U
+#define SLAP_RESTRICT_OP_RENAME 0x0040U
+#define SLAP_RESTRICT_OP_SEARCH 0x0080U
+
+#define SLAP_RESTRICT_OP_READS \
+ ( SLAP_RESTRICT_OP_COMPARE \
+ | SLAP_RESTRICT_OP_SEARCH )
+#define SLAP_RESTRICT_OP_WRITES \
+ ( SLAP_RESTRICT_OP_ADD \
+ | SLAP_RESTRICT_OP_DELETE \
+ | SLAP_RESTRICT_OP_MODIFY \
+ | SLAP_RESTRICT_OP_RENAME )
+
+#define SLAP_ALLOW_BIND_V2 0x0001U /* LDAPv2 bind */
+#define SLAP_ALLOW_BIND_ANON_CRED 0x0002U /* cred should be empty */
+#define SLAP_ALLOW_BIND_ANON_DN 0x0003U /* dn should be empty */
+
+#define SLAP_DISALLOW_BIND_ANON 0x0001U /* no anonymous */
+#define SLAP_DISALLOW_BIND_SIMPLE 0x0002U /* simple authentication */
+#define SLAP_DISALLOW_BIND_KRBV4 0x0004U /* Kerberos V4 authentication */
+
+#define SLAP_DISALLOW_TLS_2_ANON 0x0010U /* StartTLS -> Anonymous */
+#define SLAP_DISALLOW_TLS_AUTHC 0x0020U /* TLS while authenticated */
+
+ slap_mask_t be_requires; /* pre-operation requirements */
+#define SLAP_REQUIRE_BIND 0x0001U /* bind before op */
+#define SLAP_REQUIRE_LDAP_V3 0x0002U /* LDAPv3 before op */
+#define SLAP_REQUIRE_AUTHC 0x0004U /* authentication before op */
+#define SLAP_REQUIRE_SASL 0x0008U /* SASL before op */
+#define SLAP_REQUIRE_STRONG 0x0010U /* strong authentication before op */
+
+ /* Required Security Strength Factor */
+ slap_ssf_set_t be_ssf_set;
+
+ /* these should be renamed from be_ to bd_ */
+ struct berval **be_suffix; /* the DN suffixes of data in this backend */
+ struct berval **be_nsuffix; /* the normalized DN suffixes in this backend */
+ struct berval **be_suffixAlias; /* pairs of DN suffix aliases and deref values */
+ struct berval be_rootdn; /* the magic "root" name (DN) for this db */
+ struct berval be_rootndn; /* the magic "root" normalized name (DN) for this db */
+ struct berval be_rootpw; /* the magic "root" password for this db */
+ unsigned int be_max_deref_depth; /* limit for depth of an alias deref */
+#define be_sizelimit be_def_limit.lms_s_soft
+#define be_timelimit be_def_limit.lms_t_soft
+ struct slap_limits_set be_def_limit; /* default limits */
+ struct slap_limits **be_limits; /* regex-based size and time limits */
+ AccessControl *be_acl; /* access control list for this backend */
+ slap_access_t be_dfltaccess; /* access given if no acl matches */
+ struct slap_replica_info **be_replica; /* replicas of this backend (in master) */
char *be_replogfile; /* replication log file (in master) */
- char *be_updatedn; /* allowed to make changes (in replicas) */
- int be_lastmod; /* keep track of lastmodified{by,time} */
- char *be_type; /* type of database */
-
- void *be_private; /* anything the backend needs */
-
- IFP be_bind; /* backend bind routine */
- IFP be_unbind; /* backend unbind routine */
- IFP be_search; /* backend search routine */
- IFP be_compare; /* backend compare routine */
- IFP be_modify; /* backend modify routine */
- IFP be_modrdn; /* backend modrdn routine */
- IFP be_add; /* backend add routine */
- IFP be_delete; /* backend delete routine */
- IFP be_abandon; /* backend abandon routine */
- IFP be_config; /* backend config routine */
- IFP be_init; /* backend init routine */
- IFP be_close; /* backend close routine */
-} Backend;
+ struct berval be_update_ndn; /* allowed to make changes (in replicas) */
+ BerVarray be_update_refs; /* where to refer modifying clients to */
+ char *be_realm;
+ void *be_private; /* anything the backend database needs */
+};
+
+struct slap_conn;
+struct slap_op;
+
+/* Backend function typedefs */
+typedef int (BI_init) LDAP_P((BackendInfo *bi));
+typedef int (BI_config) LDAP_P((BackendInfo *bi,
+ const char *fname, int lineno,
+ int argc, char **argv));
+typedef int (BI_open) LDAP_P((BackendInfo *bi));
+typedef int (BI_close) LDAP_P((BackendInfo *bi));
+typedef int (BI_destroy) LDAP_P((BackendInfo *bi));
+
+typedef int (BI_db_init) LDAP_P((Backend *bd));
+typedef int (BI_db_config) LDAP_P((Backend *bd,
+ const char *fname, int lineno,
+ int argc, char **argv));
+typedef int (BI_db_open) LDAP_P((Backend *bd));
+typedef int (BI_db_close) LDAP_P((Backend *bd));
+typedef int (BI_db_destroy) LDAP_P((Backend *bd));
+
+typedef int (BI_op_bind) LDAP_P(( BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ struct berval *dn, struct berval *ndn, int method,
+ struct berval *cred, struct berval *edn ));
+typedef int (BI_op_unbind) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o ));
+typedef int (BI_op_search) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ struct berval *base, struct berval *nbase,
+ int scope, int deref,
+ int slimit, int tlimit,
+ Filter *f, struct berval *filterstr,
+ AttributeName *attrs, int attrsonly));
+typedef int (BI_op_compare)LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ struct berval *dn, struct berval *ndn,
+ AttributeAssertion *ava));
+typedef int (BI_op_modify) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ struct berval *dn, struct berval *ndn,
+ Modifications *m));
+typedef int (BI_op_modrdn) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ struct berval *dn, struct berval *ndn,
+ struct berval *newrdn, struct berval *nnewrdn,
+ int deleteoldrdn,
+ struct berval *newSup, struct berval *nnewSup ));
+typedef int (BI_op_add) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ Entry *e));
+typedef int (BI_op_delete) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ struct berval *dn, struct berval *ndn));
+typedef int (BI_op_abandon) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ ber_int_t msgid));
+
+typedef int (BI_op_extended) LDAP_P((
+ BackendDB *be,
+ struct slap_conn *conn,
+ struct slap_op *op,
+ const char *reqoid,
+ struct berval * reqdata,
+ char **rspoid,
+ struct berval ** rspdata,
+ LDAPControl *** rspctrls,
+ const char ** text,
+ BerVarray *refs ));
+
+typedef int (BI_entry_release_rw) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ Entry *e, int rw));
+
+typedef int (BI_chk_referrals) LDAP_P((BackendDB *bd,
+ struct slap_conn *c, struct slap_op *o,
+ struct berval *dn, struct berval *ndn,
+ const char **text ));
+
+typedef int (BI_acl_group) LDAP_P((Backend *bd,
+ struct slap_conn *c, struct slap_op *o,
+ Entry *e,
+ struct berval *bdn,
+ struct berval *edn,
+ ObjectClass *group_oc,
+ AttributeDescription *group_at ));
+
+typedef int (BI_acl_attribute) LDAP_P((Backend *bd,
+ struct slap_conn *c, struct slap_op *o,
+ Entry *e, struct berval *edn,
+ AttributeDescription *entry_at,
+ BerVarray *vals ));
+
+typedef int (BI_operational) LDAP_P((Backend *bd,
+ struct slap_conn *c, struct slap_op *o,
+ Entry *e, AttributeName *attrs, int opattrs, Attribute **a ));
+
+typedef int (BI_connection_init) LDAP_P((BackendDB *bd,
+ struct slap_conn *c));
+typedef int (BI_connection_destroy) LDAP_P((BackendDB *bd,
+ struct slap_conn *c));
+
+typedef int (BI_tool_entry_open) LDAP_P(( BackendDB *be, int mode ));
+typedef int (BI_tool_entry_close) LDAP_P(( BackendDB *be ));
+typedef ID (BI_tool_entry_first) LDAP_P(( BackendDB *be ));
+typedef ID (BI_tool_entry_next) LDAP_P(( BackendDB *be ));
+typedef Entry* (BI_tool_entry_get) LDAP_P(( BackendDB *be, ID id ));
+typedef ID (BI_tool_entry_put) LDAP_P(( BackendDB *be, Entry *e,
+ struct berval *text ));
+typedef int (BI_tool_entry_reindex) LDAP_P(( BackendDB *be, ID id ));
+typedef int (BI_tool_sync) LDAP_P(( BackendDB *be ));
+
+struct slap_backend_info {
+ char *bi_type; /* type of backend */
+
+ /*
+ * per backend type routines:
+ * bi_init: called to allocate a backend_info structure,
+ * called once BEFORE configuration file is read.
+ * bi_init() initializes this structure hence is
+ * called directly from be_initialize()
+ * bi_config: called per 'backend' specific option
+ * all such options must before any 'database' options
+ * bi_config() is called only from read_config()
+ * bi_open: called to open each database, called
+ * once AFTER configuration file is read but
+ * BEFORE any bi_db_open() calls.
+ * bi_open() is called from backend_startup()
+ * bi_close: called to close each database, called
+ * once during shutdown after all bi_db_close calls.
+ * bi_close() is called from backend_shutdown()
+ * bi_destroy: called to destroy each database, called
+ * once during shutdown after all bi_db_destroy calls.
+ * bi_destory() is called from backend_destroy()
+ */
+ BI_init *bi_init;
+ BI_config *bi_config;
+ BI_open *bi_open;
+ BI_close *bi_close;
+ BI_destroy *bi_destroy;
+
+ /*
+ * per database routines:
+ * bi_db_init: called to initialize each database,
+ * called upon reading 'database <type>'
+ * called only from backend_db_init()
+ * bi_db_config: called to configure each database,
+ * called per database to handle per database options
+ * called only from read_config()
+ * bi_db_open: called to open each database
+ * called once per database immediately AFTER bi_open()
+ * calls but before daemon startup.
+ * called only by backend_startup()
+ * bi_db_close: called to close each database
+ * called once per database during shutdown but BEFORE
+ * any bi_close call.
+ * called only by backend_shutdown()
+ * bi_db_destroy: called to destroy each database
+ * called once per database during shutdown AFTER all
+ * bi_close calls but before bi_destory calls.
+ * called only by backend_destory()
+ */
+ BI_db_init *bi_db_init;
+ BI_db_config *bi_db_config;
+ BI_db_open *bi_db_open;
+ BI_db_close *bi_db_close;
+ BI_db_destroy *bi_db_destroy;
+
+ /* LDAP Operations Handling Routines */
+ BI_op_bind *bi_op_bind;
+ BI_op_unbind *bi_op_unbind;
+ BI_op_search *bi_op_search;
+ BI_op_compare *bi_op_compare;
+ BI_op_modify *bi_op_modify;
+ BI_op_modrdn *bi_op_modrdn;
+ BI_op_add *bi_op_add;
+ BI_op_delete *bi_op_delete;
+ BI_op_abandon *bi_op_abandon;
+
+ /* Extended Operations Helper */
+ BI_op_extended *bi_extended;
+
+ /* Auxilary Functions */
+ BI_entry_release_rw *bi_entry_release_rw;
+ BI_chk_referrals *bi_chk_referrals;
+
+ BI_acl_group *bi_acl_group;
+ BI_acl_attribute *bi_acl_attribute;
+
+ BI_operational *bi_operational;
+
+ BI_connection_init *bi_connection_init;
+ BI_connection_destroy *bi_connection_destroy;
+
+ /* hooks for slap tools */
+ BI_tool_entry_open *bi_tool_entry_open;
+ BI_tool_entry_close *bi_tool_entry_close;
+ BI_tool_entry_first *bi_tool_entry_first;
+ BI_tool_entry_next *bi_tool_entry_next;
+ BI_tool_entry_get *bi_tool_entry_get;
+ BI_tool_entry_put *bi_tool_entry_put;
+ BI_tool_entry_reindex *bi_tool_entry_reindex;
+ BI_tool_sync *bi_tool_sync;
+
+#define SLAP_INDEX_ADD_OP 0x0001
+#define SLAP_INDEX_DELETE_OP 0x0002
+
+ char **bi_controls; /* supported controls */
+
+ unsigned int bi_nDB; /* number of databases of this type */
+ void *bi_private; /* anything the backend type needs */
+};
+
+#define c_authtype c_authz.sai_method
+#define c_authmech c_authz.sai_mech
+#define c_dn c_authz.sai_dn
+#define c_ndn c_authz.sai_ndn
+#define c_ssf c_authz.sai_ssf
+#define c_transport_ssf c_authz.sai_transport_ssf
+#define c_tls_ssf c_authz.sai_tls_ssf
+#define c_sasl_ssf c_authz.sai_sasl_ssf
+
+#define o_authtype o_authz.sai_method
+#define o_authmech o_authz.sai_mech
+#define o_dn o_authz.sai_dn
+#define o_ndn o_authz.sai_ndn
+#define o_ssf o_authz.sai_ssf
+#define o_transport_ssf o_authz.sai_transport_ssf
+#define o_tls_ssf o_authz.sai_tls_ssf
+#define o_sasl_ssf o_authz.sai_sasl_ssf
+
+typedef void (slap_response)( struct slap_conn *, struct slap_op *,
+ ber_tag_t, ber_int_t, ber_int_t, const char *, const char *,
+ BerVarray, const char *, struct berval *,
+ struct berval *, LDAPControl ** );
+
+typedef void (slap_sresult)( struct slap_conn *, struct slap_op *,
+ ber_int_t, const char *, const char *, BerVarray,
+ LDAPControl **, int nentries);
+
+typedef int (slap_sendentry)( BackendDB *, struct slap_conn *,
+ struct slap_op *, Entry *, AttributeName *, int, LDAPControl **);
+
+typedef struct slap_callback {
+ slap_response *sc_response;
+ slap_sresult *sc_sresult;
+ slap_sendentry *sc_sendentry;
+ void *sc_private;
+} slap_callback;
/*
* represents an operation pending from an ldap client
*/
-
-typedef struct op {
- BerElement *o_ber; /* ber of the request */
- long o_msgid; /* msgid of the request */
- unsigned long o_tag; /* tag of the request */
+typedef struct slap_op {
+ ber_int_t o_opid; /* id of this operation */
+ ber_int_t o_msgid; /* msgid of the request */
+ ber_int_t o_protocol; /* version of the LDAP protocol used by client */
+ ber_tag_t o_tag; /* tag of the request */
time_t o_time; /* time op was initiated */
- char *o_dn; /* dn bound when op was initiated */
- int o_authtype; /* auth method used to bind dn */
- /* values taken from ldap.h */
- /* LDAP_AUTH_* */
- int o_opid; /* id of this operation */
- int o_connid; /* id of conn initiating this op */
-#ifdef CLDAP
- int o_cldap; /* != 0 if this came in via CLDAP */
- struct sockaddr o_clientaddr; /* client address if via CLDAP */
- char o_searchbase; /* search base if via CLDAP */
+ unsigned long o_connid; /* id of conn initiating this op */
+ ldap_pvt_thread_t o_tid; /* thread handling this op */
+
+#define SLAP_NO_CONTROL 0
+#define SLAP_NONCRITICAL_CONTROL 1
+#define SLAP_CRITICAL_CONTROL 2
+ char o_managedsait;
+ char o_subentries;
+ char o_subentries_visibility;
+ char o_noop;
+
+ char o_abandon; /* abandon flag */
+ ldap_pvt_thread_mutex_t o_abandonmutex; /* protects o_abandon */
+
+#ifdef LDAP_CONNECTIONLESS
+ Sockaddr o_peeraddr; /* UDP peer address */
#endif
- struct op *o_next; /* next operation pending */
- pthread_t o_tid; /* thread handling this op */
- int o_abandon; /* signals op has been abandoned */
- pthread_mutex_t o_abandonmutex; /* signals op has been abandoned */
+ AuthorizationInformation o_authz;
+
+ BerElement *o_ber; /* ber of the request */
+ slap_callback *o_callback; /* callback pointers */
+ LDAPControl **o_ctrls; /* controls */
- int o_private; /* anything the backend needs */
+ void *o_private; /* anything the backend needs */
+
+ LDAP_STAILQ_ENTRY(slap_op) o_next; /* next operation in list */
} Operation;
+#define get_manageDSAit(op) ((int)(op)->o_managedsait)
+#define get_subentries(op) ((int)(op)->o_subentries)
+#define get_subentries_visibility(op) ((int)(op)->o_subentries_visibility)
+
+/*
+ * Caches the result of a backend_group check for ACL evaluation
+ */
+typedef struct slap_gacl {
+ struct slap_gacl *ga_next;
+ Backend *ga_be;
+ ObjectClass *ga_oc;
+ AttributeDescription *ga_at;
+ int ga_res;
+ ber_len_t ga_len;
+ char ga_ndn[1];
+} GroupAssertion;
+
/*
* represents a connection from an ldap client
*/
+typedef struct slap_conn {
+ int c_struct_state; /* structure management state */
+ int c_conn_state; /* connection state */
-typedef struct conn {
- Sockbuf c_sb; /* ber connection stuff */
- char *c_dn; /* current DN bound to this conn */
- pthread_mutex_t c_dnmutex; /* mutex for c_dn field */
- int c_authtype; /* auth method used to bind c_dn */
-#ifdef COMPAT
- int c_version; /* for compatibility w/2.0, 3.0 */
-#endif
- char *c_addr; /* address of client on this conn */
- char *c_domain; /* domain of client on this conn */
- Operation *c_ops; /* list of pending operations */
- pthread_mutex_t c_opsmutex; /* mutex for c_ops list & stats */
- pthread_mutex_t c_pdumutex; /* only one pdu written at a time */
- pthread_cond_t c_wcv; /* used to wait for sd write-ready*/
- int c_gettingber; /* in the middle of ber_get_next */
- BerElement *c_currentber; /* ber we're getting */
- int c_writewaiter; /* signals write-ready sd waiter */
- int c_pduwaiters; /* signals threads waiting 4 pdu */
+ ldap_pvt_thread_mutex_t c_mutex; /* protect the connection */
+ Sockbuf *c_sb; /* ber connection stuff */
+
+ /* only can be changed by connect_init */
time_t c_starttime; /* when the connection was opened */
- int c_connid; /* id of this connection for stats*/
- int c_opsinitiated; /* # ops initiated/next op id */
- int c_opscompleted; /* # ops completed */
+ time_t c_activitytime; /* when the connection was last used */
+ unsigned long c_connid; /* id of this connection for stats*/
+
+ struct berval c_listener_url; /* listener URL */
+ struct berval c_peer_domain; /* DNS name of client */
+ struct berval c_peer_name; /* peer name (trans=addr:port) */
+ struct berval c_sock_name; /* sock name (trans=addr:port) */
+
+ /* only can be changed by binding thread */
+ int c_sasl_bind_in_progress; /* multi-op bind in progress */
+ struct berval c_sasl_bind_mech; /* mech in progress */
+ struct berval c_cdn;
+
+ /* authentication backend */
+ Backend *c_authc_backend;
+
+ /* authorization backend - normally same as c_authc_backend */
+ Backend *c_authz_backend;
+
+ AuthorizationInformation c_authz;
+ GroupAssertion *c_groups;
+
+ ber_int_t c_protocol; /* version of the LDAP protocol used by client */
+
+ LDAP_STAILQ_HEAD(c_o, slap_op) c_ops; /* list of operations being processed */
+ LDAP_STAILQ_HEAD(c_po, slap_op) c_pending_ops; /* list of pending operations */
+
+ ldap_pvt_thread_mutex_t c_write_mutex; /* only one pdu written at a time */
+ ldap_pvt_thread_cond_t c_write_cv; /* used to wait for sd write-ready*/
+
+ BerElement *c_currentber; /* ber we're attempting to read */
+ int c_writewaiter; /* true if writer is waiting */
+
+#ifdef LDAP_CONNECTIONLESS
+ int c_is_udp; /* true if this is (C)LDAP over UDP */
+#endif
+#ifdef HAVE_TLS
+ int c_is_tls; /* true if this LDAP over raw TLS */
+ int c_needs_tls_accept; /* true if SSL_accept should be called */
+#endif
+ int c_sasl_layers; /* true if we need to install SASL i/o handlers */
+ void *c_sasl_context; /* SASL session context */
+ void *c_sasl_extra; /* SASL session extra stuff */
+
+ long c_n_ops_received; /* num of ops received (next op_id) */
+ long c_n_ops_executing; /* num of ops currently executing */
+ long c_n_ops_pending; /* num of ops pending execution */
+ long c_n_ops_completed; /* num of ops completed */
+
+ long c_n_get; /* num of get calls */
+ long c_n_read; /* num of read calls */
+ long c_n_write; /* num of write calls */
} Connection;
#if defined(LDAP_SYSLOG) && defined(LDAP_DEBUG)
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 ) \
- { \
- if ( ldap_debug & level ) \
- fprintf( stderr, fmt, connid, opid, arg1, arg2, arg3 );\
- if ( ldap_syslog & level ) \
- syslog( ldap_syslog_level, fmt, connid, opid, arg1, \
- arg2, arg3 ); \
- }
+ do { \
+ if ( ldap_debug & (level) ) \
+ fprintf( stderr, (fmt), (connid), (opid), (arg1), (arg2), (arg3) );\
+ if ( ldap_syslog & (level) ) \
+ syslog( ldap_syslog_level, (fmt), (connid), (opid), (arg1), \
+ (arg2), (arg3) ); \
+ } while (0)
#else
#define Statslog( level, fmt, connid, opid, arg1, arg2, arg3 )
#endif
-#ifdef NEEDPROTOS
-#include "proto-slap.h"
+
+#define SASLREGEX_REPLACE 10
+#define SASL_AUTHZ_SOURCE_ATTR "saslAuthzTo"
+#define SASL_AUTHZ_DEST_ATTR "saslAuthzFrom"
+
+typedef struct sasl_regexp {
+ char *sr_match; /* regexp match pattern */
+ char *sr_replace; /* regexp replace pattern */
+ regex_t sr_workspace; /* workspace for regexp engine */
+ regmatch_t sr_strings[SASLREGEX_REPLACE]; /* strings matching $1,$2 ... */
+ int sr_offset[SASLREGEX_REPLACE+2]; /* offsets of $1,$2... in *replace */
+} SaslRegexp_t;
+
+/*
+ * listener; need to access it from monitor backend
+ */
+typedef struct slap_listener {
+ char* sl_url;
+ char* sl_name;
+#ifdef HAVE_TLS
+ int sl_is_tls;
#endif
+#ifdef LDAP_CONNECTIONLESS
+ int sl_is_udp; /* UDP listener is also data port */
+#endif
+ ber_socket_t sl_sd;
+ Sockaddr sl_sa;
+#define sl_addr sl_sa.sa_in_addr
+} Listener;
+
+LDAP_END_DECL
+
+#include "proto-slap.h"
-#endif /* _slap_h_ */
+#endif /* _SLAP_H_ */
--- /dev/null
+# $OpenLDAP$
+#
+# stand-alone slapd config -- for testing
+# with indexing
+#
+ucdata-path ./ucdata
+#
+include ./schema/core.schema
+include ./schema/cosine.schema
+#
+include ./schema/corba.schema
+include ./schema/java.schema
+include ./schema/inetorgperson.schema
+include ./schema/krb5-kdc.schema
+include ./schema/misc.schema
+include ./schema/nis.schema
+include ./schema/openldap.schema
+#
+schemacheck on
+pidfile ./test-db/slapd.pid
+argsfile ./test-db/slapd.args
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+database @BACKEND@
+suffix "o=OpenLDAP Project,l=Internet"
+directory ./test-db
+#ldbm#index objectClass eq
+#bdb#index objectClass eq
+
+#database @BACKEND@
+#suffix "dc=example,dc=com"
+#directory ./test-repl
+#index objectClass eq