From acf13ba1f41108599198958deef57910e8096e59 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Mon, 18 Feb 2002 20:16:53 +0000 Subject: [PATCH] Remove or #ifdef experimental features --- include/ldap.h | 1882 ++++++++++---- servers/slapd/at.c | 479 ++++ servers/slapd/schema_init.c | 4683 ++++++++++++++++++++++++++++++++++ servers/slapd/schema_prep.c | 981 +++++++ servers/slapd/slap.h | 1674 ++++++++++-- tests/data/slapd-schema.conf | 36 + 6 files changed, 9129 insertions(+), 606 deletions(-) create mode 100644 servers/slapd/at.c create mode 100644 servers/slapd/schema_init.c create mode 100644 servers/slapd/schema_prep.c create mode 100644 tests/data/slapd-schema.conf diff --git a/include/ldap.h b/include/ldap.h index 1eab5bda62..d64a0eb386 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -1,4 +1,15 @@ +/* $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. * @@ -13,218 +24,310 @@ #ifndef _LDAP_H #define _LDAP_H -#ifdef __cplusplus -extern "C" { -#endif - +/* pull in lber */ +#include -#ifdef WINSOCK -#include "msdos.h" -#include -#endif +/* include version and API feature defines */ +#include -#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 @@ -232,9 +335,18 @@ typedef struct ldapmod { #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 @@ -243,31 +355,45 @@ typedef struct ldapmod { #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 @@ -279,9 +405,14 @@ typedef struct ldapmod { #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. @@ -289,89 +420,29 @@ typedef struct ldapmod { * 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 @@ -380,8 +451,8 @@ typedef struct ldapcache { 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; @@ -410,183 +481,1138 @@ typedef struct ldap_filt_desc { /* - * 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 -#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 */ diff --git a/servers/slapd/at.c b/servers/slapd/at.c new file mode 100644 index 0000000000..91015007b9 --- /dev/null +++ b/servers/slapd/at.c @@ -0,0 +1,479 @@ +/* $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 + +#include +#include +#include +#include +#include + +#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 diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c new file mode 100644 index 0000000000..d8d82496b7 --- /dev/null +++ b/servers/slapd/schema_init.c @@ -0,0 +1,4683 @@ +/* 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 +#include + +#include +#include +#include +#include + +#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 ) { + 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= 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= 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 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; jbv_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; jbv_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; jbv_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 +#include +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; idata[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; itype == 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(); +} diff --git a/servers/slapd/schema_prep.c b/servers/slapd/schema_prep.c new file mode 100644 index 0000000000..16262445b2 --- /dev/null +++ b/servers/slapd/schema_prep.c @@ -0,0 +1,981 @@ +/* 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 + +#include +#include +#include + +#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; +} diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index bf0c9c8297..25f911049f 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1,265 +1,1583 @@ /* 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 +#include + +#include +#include +#include +#include +#include +#include -#include #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 +#include -#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 */ + 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 ' + * 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_ */ diff --git a/tests/data/slapd-schema.conf b/tests/data/slapd-schema.conf new file mode 100644 index 0000000000..3bc338e167 --- /dev/null +++ b/tests/data/slapd-schema.conf @@ -0,0 +1,36 @@ +# $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 -- 2.39.5