mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-09 02:52:04 +08:00
Merged files from branch REGEX_REMOVAL. Despite name, this merge
adds POSIX RegEx (and removes BSD re_comp/re_exec) support. * POSIX RegEx is not currently included in the distribution, however we will probably add Henry Spencer's REGEX library soon. * ACL Group functionality is also included in this merge!
This commit is contained in:
parent
c636a39a60
commit
2ec25ef881
@ -232,6 +232,9 @@ LDAP_REVERSE_LOOKUP=-DREVERSE_LOOKUP
|
||||
# uncomment this line to enable support for LDAP referrals in libldap
|
||||
LDAP_REFERRALS=-DLDAP_REFERRALS
|
||||
|
||||
# uncomment this line to enable ACL by groups
|
||||
# LDAP_ACLGROUP=-DACLGROUP
|
||||
|
||||
# uncomment these lines to enable support for CRYPT passwords in LDBM.
|
||||
# LDAP_CRYPT=-DLDAP_CRYPT
|
||||
# LDAP_CRYPT_LIB?=
|
||||
|
200
Make-common.um
Normal file
200
Make-common.um
Normal file
@ -0,0 +1,200 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (c) 1994 Regents of the University of Michigan.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms are permitted
|
||||
# provided that this notice is preserved and that due credit is given
|
||||
# to the University of Michigan at Ann Arbor. The name of the University
|
||||
# may not be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission. This software
|
||||
# is provided ``as is'' without express or implied warranty.
|
||||
#
|
||||
# LDAP common Make defines (included in all but top-level Makefile)
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#############################################################################
|
||||
## Edit the following variables to have appropriate values for your system ##
|
||||
#############################################################################
|
||||
|
||||
#############################################################################
|
||||
## LDAP install paths ##
|
||||
#############################################################################
|
||||
#
|
||||
# by default, everything is installed below INSTROOT
|
||||
# servers, config files, etc. are put in ETCDIR
|
||||
# include files get put in INCLUDEDIR
|
||||
# libraries are put in LIBDIR
|
||||
# man pages are put under MANDIR
|
||||
# programs end-users will run are put in BINDIR
|
||||
#
|
||||
INSTROOT=/usr/local
|
||||
ETCDIR= $(INSTROOT)/etc
|
||||
INCLUDEDIR= $(INSTROOT)/include
|
||||
LIBDIR= $(INSTROOT)/lib
|
||||
MANDIR= $(INSTROOT)/man
|
||||
BINDIR= $(INSTROOT)/bin
|
||||
#
|
||||
# if you want things to run in a different directory from where they
|
||||
# are installed, set this accordingly (this path gets compiled into a
|
||||
# few binaries). otherwise, leave it alone.
|
||||
RUNTIMEETCDIR= $(ETCDIR)
|
||||
|
||||
#############################################################################
|
||||
## General compiler options ##
|
||||
#############################################################################
|
||||
# Passed to every compile (cc or gcc). This is where you put -O or -g, etc.
|
||||
EXTRACFLAGS=-g
|
||||
# Passed to every link (ld). Include -g here if you did in EXTRACFLAGS.
|
||||
EXTRALDFLAGS=-g
|
||||
|
||||
#############################################################################
|
||||
## If you are NOT using Kerberos authentication, you can skip this section.##
|
||||
#############################################################################
|
||||
#
|
||||
# Otherwise, to enable kerberos authentication, uncomment KERBEROS (and
|
||||
# AFSKERBEROS if you are running the AFS version of kerberos). Also
|
||||
# uncomment and change the various KRB* lines to point to where the
|
||||
# kerberos libraries and include files are installed at your site.
|
||||
#
|
||||
KERBEROS=-DKERBEROS
|
||||
AFSKERBEROS=-DAFSKERBEROS
|
||||
KRBINCLUDEFLAG = -I/usr/local/kerberos/include
|
||||
KRBLIBFLAG = -L/usr/local/kerberos/lib
|
||||
KRBLIBS = -lkrb -ldes
|
||||
|
||||
#############################################################################
|
||||
## ISODE is required ONLY to build the ldap <-> X.500 server (ldapd) ##
|
||||
## If you don't want to build it, you can skip this section. ##
|
||||
#############################################################################
|
||||
#
|
||||
# To build the ldap server, uncomment the HAVEISODE line,
|
||||
# and the section describing build settings for your version of isode.
|
||||
#
|
||||
HAVEISODE = yes
|
||||
# If you compiled ISODE with TURBO_DISK defined, uncomment this
|
||||
#ISODETURBOLIBS = -lgdbm
|
||||
# uncomment these to have ldapd "pretty print" protocol elements w/debugging
|
||||
PEPSY_DUMP=-DPEPSY_DUMP
|
||||
PEPSY=/usr/local/ic/bin/pepsy
|
||||
# uncommment this line to have ldapd load PP syntax handlers
|
||||
# you'll also need to add -lpp to ISODEBASELIBS below
|
||||
#LDAP_USE_PP=-DLDAP_USE_PP
|
||||
# uncomment NO_SETPROCTITLE to have ldapd NOT change its title
|
||||
#NO_SETPROCTITLE=-DNOSETPROCTITLE
|
||||
#
|
||||
# ISODE Consortium release build settings
|
||||
# You should change the next line so that ICRELEASE matches the (integer)
|
||||
# version number of whatever IC release you have, e.g. 1, 2, or 3 and
|
||||
# also uncomment the next 5 lines.
|
||||
ICRELEASE=-DICRELEASE=2
|
||||
ISODEPACKAGE=-DISODEPACKAGE=IC
|
||||
ISODEINCLUDEFLAG= -I/usr/local/ic/include
|
||||
ISODELIBFLAG = -L/usr/local/ic/lib
|
||||
ISODEBASELIBS = -lisode
|
||||
#
|
||||
# Freely available ISODE 8.0 release build settings (uncomment the next 4 lines)
|
||||
#ISODEPACKAGE=-DISODEPACKAGE
|
||||
#ISODEINCLUDEFLAG= -I/usr/local/isode/include
|
||||
#ISODELIBFLAG = -L/usr/local/isode/lib
|
||||
#ISODEBASELIBS = -ldsap -lisode
|
||||
#
|
||||
# NEXOR ISODE release build settings (uncomment the next 4 lines)
|
||||
#ISODEPACKAGE=-DISODEPACKAGE=XT
|
||||
#ISODEINCLUDEFLAG= -I/usr/include/isode
|
||||
#ISODELIBFLAG = -L/usr/local/lib -L/usr/sunlink/osi/lib
|
||||
#ISODEBASELIBS = -lxtpp -lresolv -lxtdsap -lxtisode -losi
|
||||
|
||||
#############################################################################
|
||||
## If you don't want to run slapd, skip this section. ##
|
||||
#############################################################################
|
||||
#
|
||||
# To build slapd (the stand-alone ldap daemon), uncomment the MAKESLAPD
|
||||
# line and select the SLAPD_BACKENDS you want to use. If you enable the
|
||||
# LDBM backend, also select one of the LDBM backends.
|
||||
MAKESLAPD= yes
|
||||
#
|
||||
# remove the defines for backends you don't want to enable
|
||||
SLAPD_BACKENDS= -DLDAP_LDBM -DLDAP_SHELL -DLDAP_PASSWD
|
||||
#
|
||||
# If you have included -DLDAP_LDBM in the SLAPD_BACKENDS line you need
|
||||
# to specify which low-level database package to use. There are
|
||||
# four choices: Berkeley db b-tree, Berkeley db hash, GNU dbm, or ndbm.
|
||||
#
|
||||
# berkeley db btree package
|
||||
LDBMBACKEND=-DLDBM_USE_DBBTREE
|
||||
LDBMINCLUDE=-I/usr/local/include
|
||||
LDBMLIB=-ldb
|
||||
# berkeley db hash package
|
||||
#LDBMBACKEND=-DLDBM_USE_DBHASH
|
||||
#LDBMINCLUDE=-I/usr/local/include
|
||||
#LDBMLIB=-ldb
|
||||
# gnu dbm (gdbm)
|
||||
#LDBMBACKEND=-DLDBM_USE_GDBM
|
||||
#LDBMINCLUDE=-I/usr/local/include
|
||||
#LDBMLIB=-lgdbm
|
||||
# standard unix ndbm
|
||||
#LDBMBACKEND=-DLDBM_USE_NDBM
|
||||
#
|
||||
# if you want to use a non-default threads package change these lines
|
||||
#THREADS=-DNO_THREADS
|
||||
#THREADSLIB=
|
||||
|
||||
#############################################################################
|
||||
## The following options are used by the xax500 client. If you haven't ##
|
||||
## retrieved the xax500 source and dropped it into the "clients" ##
|
||||
## directory, you can skip this section. ##
|
||||
#############################################################################
|
||||
#
|
||||
# location of your X include files
|
||||
#XINCLUDES= -I/usr/local/X11/include
|
||||
#
|
||||
# location of your X libraries
|
||||
#XLIBDIRS=-L/usr/local/X11/lib
|
||||
#
|
||||
# include any extra X libraries you need here
|
||||
# the following works with sunos 4 and X11R5
|
||||
#XLIBS = $(XLIBDIRS) -lXm -lXt -lX11
|
||||
# the following has been known to work with Solaris 2.4 and X11R6
|
||||
#XLIBS = $(XLIBDIRS) -lXm -lXext -lSM -lICE -lXpm -lXt -lX11
|
||||
|
||||
#############################################################################
|
||||
## If you don't want to do auto-translation of character sets, skip this ##
|
||||
#############################################################################
|
||||
#
|
||||
# Otherwise, uncomment this line and set the following options.
|
||||
#STR_TRANSLATION=-DSTR_TRANSLATION
|
||||
#
|
||||
# remove the defines for LDAP client library T.61 character translation
|
||||
# you do not need. If you use LDAP_CHARSET_8859, replace the '1' in "88591"
|
||||
# with the number of the particular character set you use. E.g., use "88594"
|
||||
# if you use the ISO 8859-4 chracter set.
|
||||
#LIBLDAP_CHARSETS=-DLDAP_CHARSET_8859="88591"
|
||||
#
|
||||
# uncomment one these lines to enable automatic T.61 translation by default
|
||||
#LIBLDAP_DEF_CHARSET=-DLDAP_DEFAULT_CHARSET=LDAP_CHARSET_8859
|
||||
|
||||
#############################################################################
|
||||
## General options ##
|
||||
#############################################################################
|
||||
# uncomment this line to enable debugging code (a good idea)
|
||||
LDAP_DEBUG=-DLDAP_DEBUG
|
||||
|
||||
# uncomment this line to turn on a few U of Michigan specific things
|
||||
UOFM=-DUOFM
|
||||
|
||||
# uncomment this line to delete a few printfs in the lber and ldap libraries.
|
||||
#NO_USERINTERFACE=-DNO_USERINTERFACE
|
||||
|
||||
# uncomment this line to include Connectionless LDAP support
|
||||
CLDAP=-DCLDAP
|
||||
|
||||
# uncomment this line to eliminate local caching support in the libldap
|
||||
#NO_CACHE=-DNO_CACHE
|
||||
|
||||
# uncomment this line to enable support for LDAP referrals in libldap
|
||||
LDAP_REFERRALS=-DLDAP_REFERRALS
|
||||
|
||||
# uncomment this line to use soundex for approximate matches in slapd.
|
||||
# the default is to use the metaphone algorithm.
|
||||
#PHONETIC=-DSOUNDEX
|
@ -21,15 +21,18 @@
|
||||
# DEFS are included in CFLAGS
|
||||
DEFS = $(PLATFORMCFLAGS) $(LDAP_DEBUG) $(KERBEROS) $(AFSKERBEROS) \
|
||||
$(UOFM) $(UOFA) $(NO_USERINTERFACE) $(CLDAP) $(NO_CACHE) \
|
||||
$(LDAP_REVERSE_LOOKUP) \
|
||||
$(LDAP_REFERRALS) $(LDAP_DNS) $(STR_TRANSLATION) \
|
||||
$(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET) \
|
||||
$(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE) $(PHONETIC)
|
||||
$(LIBLDAP_CHARSETS) $(LIBLDAP_DEF_CHARSET)
|
||||
|
||||
# LDBMDEFS are included by servers (though only slapd only cares)
|
||||
# and libldbm
|
||||
LDBMDEFS = $(SLAPD_BACKENDS) $(LDBMBACKEND) $(LDBMINCLUDE)
|
||||
|
||||
# SERVERDEFS are added to server builds CFLAGS (in addition to DEFS)
|
||||
SERVERDEFS = $(ISODEPACKAGE) $(ICRELEASE) $(LDAP_USE_PP) \
|
||||
$(NO_SETPROCTITLE) $(PEPSY_DUMP)
|
||||
|
||||
$(NO_SETPROCTITLE) $(PEPSY_DUMP) \
|
||||
$(LDAP_REVERSE_LOOKUP) $(LDAP_CRYPT) $(LDAP_ACLGROUP) \
|
||||
$(PHONETIC) $(LDBMDEFS)
|
||||
#
|
||||
# ISODELIBS are used in server/ldapd builds
|
||||
#
|
||||
|
@ -44,4 +44,3 @@ LDAP_CRYPT_LIB= -lcrypt
|
||||
# -------------------------------------------------------------------------
|
||||
CC = gcc
|
||||
PLATFORMCFLAGS= -Dfreebsd
|
||||
PLATFORMLIBS=-lcompat
|
||||
|
273
include/ldapconfig.h.um
Normal file
273
include/ldapconfig.h.um
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (c) 1994 Regents of the University of Michigan.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that this notice is preserved and that due credit is given
|
||||
* to the University of Michigan at Ann Arbor. The name of the University
|
||||
* may not be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission. This software
|
||||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
/*
|
||||
* config.h for LDAP -- edit this file to customize LDAP client behavior.
|
||||
* NO platform-specific definitions should be placed in this file.
|
||||
* Note that this is NOT used by the LDAP or LBER libraries.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SHARED DEFINITIONS - things you should change
|
||||
*/
|
||||
/* default ldap host */
|
||||
#define LDAPHOST "ldap.itd.umich.edu"
|
||||
/* default place to start searching */
|
||||
#define DEFAULT_BASE "o=University of Michigan, c=US"
|
||||
|
||||
/*********************************************************************
|
||||
* *
|
||||
* You probably do not need to edit anything below this point *
|
||||
* *
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* SHARED DEFINITIONS - other things you can change
|
||||
*/
|
||||
/* default attribute to use when sorting entries, NULL => sort by DN */
|
||||
#define SORT_ATTR NULL
|
||||
/* default count of DN components to show in entry displays */
|
||||
#define DEFAULT_RDNCOUNT 2
|
||||
/* default config file locations */
|
||||
#define FILTERFILE "%ETCDIR%/ldapfilter.conf"
|
||||
#define TEMPLATEFILE "%ETCDIR%/ldaptemplates.conf"
|
||||
#define SEARCHFILE "%ETCDIR%/ldapsearchprefs.conf"
|
||||
#define FRIENDLYFILE "%ETCDIR%/ldapfriendly"
|
||||
|
||||
/*
|
||||
* FINGER DEFINITIONS
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define FINGER_BINDDN "cn=finger, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* where to search */
|
||||
#define FINGER_BASE DEFAULT_BASE
|
||||
/* banner to print */
|
||||
#define FINGER_BANNER "X.500 Finger Service...\r\n"
|
||||
/* who to report errors to */
|
||||
#define FINGER_ERRORS "x500@umich.edu"
|
||||
/* what to say if no matches are found */
|
||||
#define FINGER_NOMATCH \
|
||||
"Search failed to find anything. Currently, this service contains\r\n\
|
||||
information only on University of Michigan faculty, staff, and students.\r\n\
|
||||
Other likely places to finger are:\r\n\
|
||||
um.cc.umich.edu\r\n\
|
||||
azure.engin.umich.edu\r\n"
|
||||
/* what to say if the service may be unavailable */
|
||||
#define FINGER_UNAVAILABLE \
|
||||
"The X.500 service may be temporarily unavailable.\r\n\
|
||||
Please try again later.\r\n"
|
||||
/* printed if a match has no email address - for disptmp default */
|
||||
#define FINGER_NOEMAIL1 "None registered in this service. Try fingering at:"
|
||||
#define FINGER_NOEMAIL2 "um.cc.umich.edu or azure.engin.umich.edu"
|
||||
#define FINGER_NOEMAIL { FINGER_NOEMAIL1, FINGER_NOEMAIL2, NULL }
|
||||
/* maximum number of matches returned */
|
||||
#define FINGER_SIZELIMIT 50
|
||||
/* max number of hits displayed in full before a list is presented */
|
||||
#define FINGER_LISTLIMIT 1
|
||||
/* what to exec for "finger @host" */
|
||||
#define FINGER_CMD "/usr/ucb/finger"
|
||||
/* how to treat aliases when searching */
|
||||
#define FINGER_DEREF LDAP_DEREF_FINDING
|
||||
/* attribute to use when sorting results */
|
||||
#define FINGER_SORT_ATTR SORT_ATTR
|
||||
/* enable ufn support */
|
||||
#define FINGER_UFN
|
||||
/* timeout for searches */
|
||||
#define FINGER_TIMEOUT 60
|
||||
/* number of DN components to show in entry displays */
|
||||
#define FINGER_RDNCOUNT DEFAULT_RDNCOUNT
|
||||
|
||||
/*
|
||||
* GO500 GOPHER GATEWAY DEFINITIONS
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define GO500_BINDDN "cn=go500, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* where to search */
|
||||
#define GO500_BASE DEFAULT_BASE
|
||||
/* port on which to listen */
|
||||
#define GO500_PORT 5555
|
||||
/* how to handle aliases */
|
||||
#define GO500_DEREF LDAP_DEREF_FINDING
|
||||
/* attribute to use when sorting results */
|
||||
#define GO500_SORT_ATTR SORT_ATTR
|
||||
/* timeout for searches */
|
||||
#define GO500_TIMEOUT 60
|
||||
/* enable ufn support */
|
||||
#define GO500_UFN
|
||||
/*
|
||||
* only set and uncomment this if your hostname() does not return
|
||||
* a fully qualified hostname
|
||||
*/
|
||||
/* #define GO500_HOSTNAME "fully.qualified.hostname.here" */
|
||||
/* number of DN components to show in entry displays */
|
||||
#define GO500_RDNCOUNT DEFAULT_RDNCOUNT
|
||||
|
||||
/*
|
||||
* GO500GW GOPHER GATEWAY DEFINITIONS
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define GO500GW_BINDDN "cn=go500gw, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* where the helpfile lives */
|
||||
#define GO500GW_HELPFILE "%ETCDIR%/go500gw.help"
|
||||
/* port on which to listen */
|
||||
#define GO500GW_PORT 7777
|
||||
/* timeout on all searches */
|
||||
#define GO500GW_TIMEOUT 180
|
||||
/* enable ufn support */
|
||||
#define GO500GW_UFN
|
||||
/* attribute to use when sorting results */
|
||||
#define GO500GW_SORT_ATTR SORT_ATTR
|
||||
/*
|
||||
* only set and uncomment this if your hostname() does not return
|
||||
* a fully qualified hostname
|
||||
*/
|
||||
/* #define GO500GW_HOSTNAME "fully.qualified.hostname.here" */
|
||||
/* number of DN components to show in entry displays */
|
||||
#define GO500GW_RDNCOUNT DEFAULT_RDNCOUNT
|
||||
|
||||
/*
|
||||
* RCPT500 MAIL RESPONDER GATEWAY DEFINITIONS
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define RCPT500_BINDDN "cn=Rcpt500, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* where the helpfile lives */
|
||||
#define RCPT500_HELPFILE "%ETCDIR%/rcpt500.help"
|
||||
/* maximum number of matches returned */
|
||||
#define RCPT500_SIZELIMIT 50
|
||||
/* address replies will appear to come from */
|
||||
#define RCPT500_FROM "\"X.500 Query Program\" <X500-Query>"
|
||||
/* command that will accept an RFC822 message text on standard
|
||||
input, and send it. sendmail -t does this nicely. */
|
||||
#define RCPT500_PIPEMAILCMD "/usr/lib/sendmail -t"
|
||||
/* where to search */
|
||||
#define RCPT500_BASE DEFAULT_BASE
|
||||
/* attribute to use when sorting results */
|
||||
#define RCPT500_SORT_ATTR SORT_ATTR
|
||||
/* max number of hits displayed in full before a list is presented */
|
||||
#define RCPT500_LISTLIMIT 3
|
||||
/* enable ufn support */
|
||||
#define RCPT500_UFN
|
||||
/* number of DN components to show in entry displays */
|
||||
#define RCPT500_RDNCOUNT DEFAULT_RDNCOUNT
|
||||
|
||||
/*
|
||||
* LDAPSEARCH TOOL
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define LDAPSEARCH_BINDDN "cn=LDAP Search Tool, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* search base */
|
||||
#define LDAPSEARCH_BASE DEFAULT_BASE
|
||||
|
||||
/*
|
||||
* LDAPMODIFY TOOL
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define LDAPMODIFY_BINDDN "cn=Manager, o=University of Michigan, c=US"
|
||||
/* search base */
|
||||
#define LDAPMODIFY_BASE DEFAULT_BASE
|
||||
|
||||
/*
|
||||
* LDAPDELETE TOOL
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define LDAPDELETE_BINDDN "cn=Manager, o=University of Michigan, c=US"
|
||||
/* search base */
|
||||
#define LDAPDELETE_BASE DEFAULT_BASE
|
||||
|
||||
/*
|
||||
* LDAPMODRDN TOOL
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define LDAPMODRDN_BINDDN "cn=Manager, o=University of Michigan, c=US"
|
||||
/* search base */
|
||||
#define LDAPMODRDN_BASE DEFAULT_BASE
|
||||
|
||||
/*
|
||||
* MAIL500 MAILER DEFINITIONS
|
||||
*/
|
||||
/* who to bind as */
|
||||
#define MAIL500_BINDDN "cn=mail500, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* max number of ambiguous matches reported */
|
||||
#define MAIL500_MAXAMBIGUOUS 10
|
||||
/* max subscribers allowed (size limit when searching for them ) */
|
||||
#define MAIL500_MAXGROUPMEMBERS LDAP_NO_LIMIT
|
||||
/* timeout for all searches */
|
||||
#define MAIL500_TIMEOUT 180
|
||||
/* sendmail location - mail500 needs to exec this */
|
||||
#define MAIL500_SENDMAIL "/usr/lib/sendmail"
|
||||
|
||||
/*
|
||||
* UD DEFINITIONS
|
||||
*/
|
||||
/* ud configuration file */
|
||||
#define UD_CONFIG_FILE "%ETCDIR%/ud.conf"
|
||||
/* default editor */
|
||||
#define UD_DEFAULT_EDITOR "/usr/ucb/vi"
|
||||
/* default bbasename of user config file */
|
||||
#define UD_USER_CONFIG_FILE ".udrc"
|
||||
/* default user to bind as */
|
||||
#define UD_BINDDN "cn=ud, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* default password to bind with */
|
||||
#define UD_PASSWD NULL
|
||||
/* default search base */
|
||||
#define UD_BASE DEFAULT_BASE
|
||||
/* default base where groups are created */
|
||||
#define UD_WHERE_GROUPS_ARE_CREATED "ou=User Groups, ou=Groups, o=University of Michigan, c=US"
|
||||
/* default base below which all groups live */
|
||||
#define UD_WHERE_ALL_GROUPS_LIVE "ou=Groups, o=University of Michigan, c=US"
|
||||
|
||||
/*
|
||||
* FAX500 DEFINITIONS
|
||||
*/
|
||||
/* what to bind as */
|
||||
#define FAX_BINDDN "cn=mail500, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* how long to wait for searches */
|
||||
#define FAX_TIMEOUT 180
|
||||
/* maximum number of ambiguous matches reported */
|
||||
#define FAX_MAXAMBIGUOUS 10
|
||||
/* maximum number of members allowed */
|
||||
#define FAX_MAXMEMBERS LDAP_NO_LIMIT
|
||||
/* program to send mail */
|
||||
#define FAX_SENDMAIL "/usr/lib/sendmail"
|
||||
|
||||
/*
|
||||
* RP500 DEFINITIONS
|
||||
*/
|
||||
/* what to bind as */
|
||||
#define RP_BINDDN "cn=rp500, ou=Miscellaneous Servers, o=University of Michigan, c=US"
|
||||
/* prefix to add to non-fully-qualified numbers */
|
||||
#define RP_PHONEPREFIX "1313"
|
||||
|
||||
/*
|
||||
* SLAPD DEFINITIONS
|
||||
*/
|
||||
/* location of the default slapd config file */
|
||||
#define SLAPD_DEFAULT_CONFIGFILE "%ETCDIR%/slapd.conf"
|
||||
/* default sizelimit on number of entries from a search */
|
||||
#define SLAPD_DEFAULT_SIZELIMIT 500
|
||||
/* default timelimit to spend on a search */
|
||||
#define SLAPD_DEFAULT_TIMELIMIT 3600
|
||||
/* location of the slapd pid file */
|
||||
#define SLAPD_PIDFILE "%ETCDIR%/slapd.pid"
|
||||
/* location of the slapd args file */
|
||||
#define SLAPD_ARGSFILE "%ETCDIR%/slapd.args"
|
||||
/* dn of the special "monitor" entry */
|
||||
#define SLAPD_MONITOR_DN "cn=monitor"
|
||||
/* dn of the special "config" entry */
|
||||
#define SLAPD_CONFIG_DN "cn=config"
|
||||
/* minimum max ids that a single index entry can map to in ldbm */
|
||||
#define SLAPD_LDBM_MIN_MAXIDS 4000
|
||||
|
||||
#endif /* _CONFIG_H */
|
@ -17,13 +17,13 @@ LDAPSRC = ../..
|
||||
|
||||
SRCS = bind.c open.c result.c error.c compare.c search.c \
|
||||
modify.c add.c modrdn.c delete.c abandon.c ufn.c cache.c \
|
||||
getfilter.c regex.c sbind.c kbind.c unbind.c friendly.c cldap.c \
|
||||
getfilter.c sbind.c kbind.c unbind.c friendly.c cldap.c \
|
||||
free.c disptmpl.c srchpref.c dsparse.c tmplout.c sort.c \
|
||||
getdn.c getentry.c getattr.c getvalues.c addentry.c \
|
||||
request.c getdxbyname.c os-ip.c url.c charset.c
|
||||
OBJS = bind.o open.o result.o error.o compare.o search.o \
|
||||
modify.o add.o modrdn.o delete.o abandon.o ufn.o cache.o \
|
||||
getfilter.o regex.o sbind.o kbind.o unbind.o friendly.o cldap.o \
|
||||
getfilter.o sbind.o kbind.o unbind.o friendly.o cldap.o \
|
||||
free.o disptmpl.o srchpref.o dsparse.o tmplout.o sort.o \
|
||||
getdn.o getentry.o getattr.o getvalues.o addentry.o \
|
||||
request.o getdxbyname.o os-ip.o url.o charset.o
|
||||
|
@ -10,13 +10,13 @@ static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#if defined(NeXT)
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
#endif
|
||||
|
||||
#ifdef MACOS
|
||||
#include <stdlib.h>
|
||||
#include "macos.h"
|
||||
#else /* MACOS */
|
||||
#ifdef DOS
|
||||
@ -25,7 +25,6 @@ static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of
|
||||
#else /* DOS */
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/errno.h>
|
||||
#ifndef VMS
|
||||
#include <unistd.h>
|
||||
@ -35,7 +34,6 @@ static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of
|
||||
|
||||
#include "lber.h"
|
||||
#include "ldap.h"
|
||||
#include "regex.h"
|
||||
|
||||
#ifdef NEEDPROTOS
|
||||
static int break_into_words( char *str, char *delims, char ***wordsp );
|
||||
@ -49,7 +47,6 @@ void free_strarray();
|
||||
|
||||
#if !defined( MACOS ) && !defined( DOS )
|
||||
extern int errno;
|
||||
extern char *re_comp();
|
||||
#endif
|
||||
|
||||
#define FILT_MAX_LINE_LEN 1024
|
||||
@ -107,8 +104,10 @@ ldap_init_getfilter_buf( char *buf, long buflen )
|
||||
LDAPFiltDesc *lfdp;
|
||||
LDAPFiltList *flp, *nextflp;
|
||||
LDAPFiltInfo *fip, *nextfip;
|
||||
char *tag, **tok;
|
||||
int tokcnt, i;
|
||||
char *tag, **tok;
|
||||
int tokcnt, i;
|
||||
int rc;
|
||||
regex_t re;
|
||||
|
||||
if (( lfdp = (LDAPFiltDesc *)calloc( 1, sizeof( LDAPFiltDesc))) == NULL ) {
|
||||
return( NULL );
|
||||
@ -138,11 +137,13 @@ ldap_init_getfilter_buf( char *buf, long buflen )
|
||||
}
|
||||
nextflp->lfl_tag = strdup( tag );
|
||||
nextflp->lfl_pattern = tok[ 0 ];
|
||||
if ( re_comp( nextflp->lfl_pattern ) != NULL ) {
|
||||
if ( (rc = regcomp( &re, nextflp->lfl_pattern, 0 )) != 0 ) {
|
||||
#ifndef NO_USERINTERFACE
|
||||
char error[512];
|
||||
regerror(rc, &re, error, sizeof(error));
|
||||
ldap_getfilter_free( lfdp );
|
||||
fprintf( stderr, "bad regular expresssion %s\n",
|
||||
nextflp->lfl_pattern );
|
||||
fprintf( stderr, "bad regular expresssion %s, %s\n",
|
||||
nextflp->lfl_pattern, error );
|
||||
#if !defined( MACOS ) && !defined( DOS )
|
||||
errno = EINVAL;
|
||||
#endif
|
||||
@ -150,6 +151,7 @@ ldap_init_getfilter_buf( char *buf, long buflen )
|
||||
free_strarray( tok );
|
||||
return( NULL );
|
||||
}
|
||||
regfree(&re);
|
||||
|
||||
nextflp->lfl_delims = tok[ 1 ];
|
||||
nextflp->lfl_ilist = NULL;
|
||||
@ -247,6 +249,8 @@ LDAPFiltInfo *
|
||||
ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
|
||||
{
|
||||
LDAPFiltList *flp;
|
||||
int rc;
|
||||
regex_t re;
|
||||
|
||||
if ( lfdp->lfd_curvalcopy != NULL ) {
|
||||
free( lfdp->lfd_curvalcopy );
|
||||
@ -256,13 +260,30 @@ ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value )
|
||||
lfdp->lfd_curval = value;
|
||||
lfdp->lfd_curfip = NULL;
|
||||
|
||||
for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
|
||||
if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1
|
||||
&& re_comp( flp->lfl_pattern ) == NULL
|
||||
&& re_exec( lfdp->lfd_curval ) == 1 ) {
|
||||
lfdp->lfd_curfip = flp->lfl_ilist;
|
||||
break;
|
||||
}
|
||||
for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) {
|
||||
/* compile tagpat, continue if we fail */
|
||||
if (regcomp(&re, tagpat, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* match tagpatern and tag, continue if we fail */
|
||||
rc = regexec(&re, flp->lfl_tag, 0, NULL, 0);
|
||||
regfree(&re);
|
||||
if (rc != 0)
|
||||
continue;
|
||||
|
||||
/* compile flp->ifl_pattern, continue if we fail */
|
||||
if (regcomp(&re, flp->lfl_pattern, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* match ifl_pattern and lfd_curval, continue if we fail */
|
||||
rc = regexec(&re, lfdp->lfd_curval, 0, NULL, 0);
|
||||
regfree(&re);
|
||||
if (rc != 0)
|
||||
continue;
|
||||
|
||||
/* we successfully compiled both patterns and matched both values */
|
||||
lfdp->lfd_curfip = flp->lfl_ilist;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( lfdp->lfd_curfip == NULL ) {
|
||||
|
@ -1,905 +0,0 @@
|
||||
#include "portable.h"
|
||||
|
||||
#if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || defined( NEED_BSDREGEX )
|
||||
#include "regex.h"
|
||||
|
||||
/*
|
||||
* regex - Regular expression pattern matching and replacement
|
||||
*
|
||||
* By: Ozan S. Yigit (oz)
|
||||
* Dept. of Computer Science
|
||||
* York University
|
||||
*
|
||||
* These routines are the PUBLIC DOMAIN equivalents of regex
|
||||
* routines as found in 4.nBSD UN*X, with minor extensions.
|
||||
*
|
||||
* These routines are derived from various implementations found
|
||||
* in software tools books, and Conroy's grep. They are NOT derived
|
||||
* from licensed/restricted software.
|
||||
* For more interesting/academic/complicated implementations,
|
||||
* see Henry Spencer's regexp routines, or GNU Emacs pattern
|
||||
* matching module.
|
||||
*
|
||||
* Vendor Modification history:
|
||||
*
|
||||
* Revision 1.12 1996/04/25 16:20:59 mcs
|
||||
* make re_exec() match "" with ".*" and similar patterns
|
||||
* hopefully this change doesn't break anything else!
|
||||
*
|
||||
* Revision 1.11 1994/12/14 21:33:45 mcs
|
||||
* use new NEED_BSDREGEX
|
||||
* fix pmatch() prototype
|
||||
*
|
||||
* Revision 1.10 1994/12/12 18:16:39 mcs
|
||||
* use on NetBSD
|
||||
*
|
||||
* Revision 1.9 1994/11/15 19:16:35 mcs
|
||||
* add (CHAR) cast to make VisualC++ happy
|
||||
*
|
||||
* Revision 1.8 1994/11/08 21:14:32 mcs
|
||||
* WIN32 changes
|
||||
*
|
||||
* Revision 1.7 1994/07/23 19:51:24 mcs
|
||||
* use ANSI-style inline function parameters
|
||||
*
|
||||
* Revision 1.6 1993/10/18 01:52:32 tim
|
||||
* include for VMS
|
||||
*
|
||||
* Revision 1.5 1993/09/28 21:37:54 mcs
|
||||
* HP/UX needs the regex we include (not in its libc)
|
||||
*
|
||||
* Revision 1.4 1993/08/27 15:59:52 mcs
|
||||
* use CHAR for deftab
|
||||
*
|
||||
* Revision 1.3 1993/08/27 15:49:47 mcs
|
||||
* added missing 0 to octal constants
|
||||
* use unsigned char for CHAR under DOS
|
||||
*
|
||||
* Revision 1.2 1993/08/27 14:57:48 mcs
|
||||
* add proto. for pmatch
|
||||
*
|
||||
* Revision 1.1 1993/08/18 21:20:02 mcs
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.4 1991/10/17 03:56:42 oz
|
||||
* miscellaneous changes, small cleanups etc.
|
||||
*
|
||||
* Revision 1.3 1989/04/01 14:18:09 oz
|
||||
* Change all references to a dfa: this is actually an nfa.
|
||||
*
|
||||
* Revision 1.2 88/08/28 15:36:04 oz
|
||||
* Use a complement bitmap to represent NCL.
|
||||
* This removes the need to have seperate
|
||||
* code in the pmatch case block - it is
|
||||
* just CCL code now.
|
||||
*
|
||||
* Use the actual CCL code in the CLO
|
||||
* section of pmatch. No need for a recursive
|
||||
* pmatch call.
|
||||
*
|
||||
* Use a bitmap table to set char bits in an
|
||||
* 8-bit chunk.
|
||||
*
|
||||
* Interfaces:
|
||||
* re_comp: compile a regular expression into a NFA.
|
||||
*
|
||||
* char *re_comp(s)
|
||||
* char *s;
|
||||
*
|
||||
* re_exec: execute the NFA to match a pattern.
|
||||
*
|
||||
* int re_exec(s)
|
||||
* char *s;
|
||||
*
|
||||
* re_modw change re_exec's understanding of what a "word"
|
||||
* looks like (for \< and \>) by adding into the
|
||||
* hidden word-syntax table.
|
||||
*
|
||||
* void re_modw(s)
|
||||
* char *s;
|
||||
*
|
||||
* re_subs: substitute the matched portions in a new string.
|
||||
*
|
||||
* int re_subs(src, dst)
|
||||
* char *src;
|
||||
* char *dst;
|
||||
*
|
||||
* re_fail: failure routine for re_exec.
|
||||
*
|
||||
* void re_fail(msg, op)
|
||||
* char *msg;
|
||||
* char op;
|
||||
*
|
||||
* Regular Expressions:
|
||||
*
|
||||
* [1] char matches itself, unless it is a special
|
||||
* character (metachar): . \ [ ] * + ^ $
|
||||
*
|
||||
* [2] . matches any character.
|
||||
*
|
||||
* [3] \ matches the character following it, except
|
||||
* when followed by a left or right round bracket,
|
||||
* a digit 1 to 9 or a left or right angle bracket.
|
||||
* (see [7], [8] and [9])
|
||||
* It is used as an escape character for all
|
||||
* other meta-characters, and itself. When used
|
||||
* in a set ([4]), it is treated as an ordinary
|
||||
* character.
|
||||
*
|
||||
* [4] [set] matches one of the characters in the set.
|
||||
* If the first character in the set is "^",
|
||||
* it matches a character NOT in the set, i.e.
|
||||
* complements the set. A shorthand S-E is
|
||||
* used to specify a set of characters S upto
|
||||
* E, inclusive. The special characters "]" and
|
||||
* "-" have no special meaning if they appear
|
||||
* as the first chars in the set.
|
||||
* examples: match:
|
||||
*
|
||||
* [a-z] any lowercase alpha
|
||||
*
|
||||
* [^]-] any char except ] and -
|
||||
*
|
||||
* [^A-Z] any char except uppercase
|
||||
* alpha
|
||||
*
|
||||
* [a-zA-Z] any alpha
|
||||
*
|
||||
* [5] * any regular expression form [1] to [4], followed by
|
||||
* closure char (*) matches zero or more matches of
|
||||
* that form.
|
||||
*
|
||||
* [6] + same as [5], except it matches one or more.
|
||||
*
|
||||
* [7] a regular expression in the form [1] to [10], enclosed
|
||||
* as \(form\) matches what form matches. The enclosure
|
||||
* creates a set of tags, used for [8] and for
|
||||
* pattern substution. The tagged forms are numbered
|
||||
* starting from 1.
|
||||
*
|
||||
* [8] a \ followed by a digit 1 to 9 matches whatever a
|
||||
* previously tagged regular expression ([7]) matched.
|
||||
*
|
||||
* [9] \< a regular expression starting with a \< construct
|
||||
* \> and/or ending with a \> construct, restricts the
|
||||
* pattern matching to the beginning of a word, and/or
|
||||
* the end of a word. A word is defined to be a character
|
||||
* string beginning and/or ending with the characters
|
||||
* A-Z a-z 0-9 and _. It must also be preceded and/or
|
||||
* followed by any character outside those mentioned.
|
||||
*
|
||||
* [10] a composite regular expression xy where x and y
|
||||
* are in the form [1] to [10] matches the longest
|
||||
* match of x followed by a match for y.
|
||||
*
|
||||
* [11] ^ a regular expression starting with a ^ character
|
||||
* $ and/or ending with a $ character, restricts the
|
||||
* pattern matching to the beginning of the line,
|
||||
* or the end of line. [anchors] Elsewhere in the
|
||||
* pattern, ^ and $ are treated as ordinary characters.
|
||||
*
|
||||
*
|
||||
* Acknowledgements:
|
||||
*
|
||||
* HCR's Hugh Redelmeier has been most helpful in various
|
||||
* stages of development. He convinced me to include BOW
|
||||
* and EOW constructs, originally invented by Rob Pike at
|
||||
* the University of Toronto.
|
||||
*
|
||||
* References:
|
||||
* Software tools Kernighan & Plauger
|
||||
* Software tools in Pascal Kernighan & Plauger
|
||||
* Grep [rsx-11 C dist] David Conroy
|
||||
* ed - text editor Un*x Programmer's Manual
|
||||
* Advanced editing on Un*x B. W. Kernighan
|
||||
* RegExp routines Henry Spencer
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* This implementation uses a bit-set representation for character
|
||||
* classes for speed and compactness. Each character is represented
|
||||
* by one bit in a 128-bit block. Thus, CCL always takes a
|
||||
* constant 16 bytes in the internal nfa, and re_exec does a single
|
||||
* bit comparison to locate the character in the set.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* pattern: foo*.*
|
||||
* compile: CHR f CHR o CLO CHR o END CLO ANY END END
|
||||
* matches: fo foo fooo foobar fobar foxx ...
|
||||
*
|
||||
* pattern: fo[ob]a[rz]
|
||||
* compile: CHR f CHR o CCL bitset CHR a CCL bitset END
|
||||
* matches: fobar fooar fobaz fooaz
|
||||
*
|
||||
* pattern: foo\\+
|
||||
* compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END
|
||||
* matches: foo\ foo\\ foo\\\ ...
|
||||
*
|
||||
* pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo)
|
||||
* compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
|
||||
* matches: foo1foo foo2foo foo3foo
|
||||
*
|
||||
* pattern: \(fo.*\)-\1
|
||||
* compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
|
||||
* matches: foo-foo fo-fo fob-fob foobar-foobar ...
|
||||
*/
|
||||
|
||||
#define MAXNFA 1024
|
||||
#define MAXTAG 10
|
||||
|
||||
#define OKP 1
|
||||
#define NOP 0
|
||||
|
||||
#define CHR 1
|
||||
#define ANY 2
|
||||
#define CCL 3
|
||||
#define BOL 4
|
||||
#define EOL 5
|
||||
#define BOT 6
|
||||
#define EOT 7
|
||||
#define BOW 8
|
||||
#define EOW 9
|
||||
#define REF 10
|
||||
#define CLO 11
|
||||
|
||||
#define END 0
|
||||
|
||||
/*
|
||||
* The following defines are not meant to be changeable.
|
||||
* They are for readability only.
|
||||
*/
|
||||
#define MAXCHR 128
|
||||
#define CHRBIT 8
|
||||
#define BITBLK MAXCHR/CHRBIT
|
||||
#define BLKIND 0170
|
||||
#define BITIND 07
|
||||
|
||||
#define ASCIIB 0177
|
||||
|
||||
#if defined( DOS ) || defined( _WIN32 )
|
||||
typedef unsigned char CHAR;
|
||||
#else /* DOS */
|
||||
typedef /*unsigned*/ char CHAR;
|
||||
#endif /* DOS */
|
||||
|
||||
static int tagstk[MAXTAG]; /* subpat tag stack..*/
|
||||
static CHAR nfa[MAXNFA]; /* automaton.. */
|
||||
static int sta = NOP; /* status of lastpat */
|
||||
|
||||
static CHAR bittab[BITBLK]; /* bit table for CCL */
|
||||
/* pre-set bits... */
|
||||
static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
|
||||
|
||||
static void
|
||||
chset(CHAR c)
|
||||
{
|
||||
bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
|
||||
}
|
||||
|
||||
#define badpat(x) (*nfa = END, x)
|
||||
#define store(x) *mp++ = x
|
||||
|
||||
char *
|
||||
re_comp( char *pat )
|
||||
{
|
||||
register char *p; /* pattern pointer */
|
||||
register CHAR *mp=nfa; /* nfa pointer */
|
||||
register CHAR *lp; /* saved pointer.. */
|
||||
register CHAR *sp=nfa; /* another one.. */
|
||||
|
||||
register int tagi = 0; /* tag stack index */
|
||||
register int tagc = 1; /* actual tag count */
|
||||
|
||||
register int n;
|
||||
register CHAR mask; /* xor mask -CCL/NCL */
|
||||
int c1, c2;
|
||||
|
||||
if (!pat || !*pat)
|
||||
if (sta)
|
||||
return 0;
|
||||
else
|
||||
return badpat("No previous regular expression");
|
||||
sta = NOP;
|
||||
|
||||
for (p = pat; *p; p++) {
|
||||
lp = mp;
|
||||
switch(*p) {
|
||||
|
||||
case '.': /* match any char.. */
|
||||
store(ANY);
|
||||
break;
|
||||
|
||||
case '^': /* match beginning.. */
|
||||
if (p == pat)
|
||||
store(BOL);
|
||||
else {
|
||||
store(CHR);
|
||||
store(*p);
|
||||
}
|
||||
break;
|
||||
|
||||
case '$': /* match endofline.. */
|
||||
if (!*(p+1))
|
||||
store(EOL);
|
||||
else {
|
||||
store(CHR);
|
||||
store(*p);
|
||||
}
|
||||
break;
|
||||
|
||||
case '[': /* match char class..*/
|
||||
store(CCL);
|
||||
|
||||
if (*++p == '^') {
|
||||
mask = 0377;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
mask = 0;
|
||||
|
||||
if (*p == '-') /* real dash */
|
||||
chset(*p++);
|
||||
if (*p == ']') /* real brac */
|
||||
chset(*p++);
|
||||
while (*p && *p != ']') {
|
||||
if (*p == '-' && *(p+1) && *(p+1) != ']') {
|
||||
p++;
|
||||
c1 = *(p-2) + 1;
|
||||
c2 = *p++;
|
||||
while (c1 <= c2)
|
||||
chset((CHAR)c1++);
|
||||
}
|
||||
#ifdef EXTEND
|
||||
else if (*p == '\\' && *(p+1)) {
|
||||
p++;
|
||||
chset(*p++);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
chset(*p++);
|
||||
}
|
||||
if (!*p)
|
||||
return badpat("Missing ]");
|
||||
|
||||
for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
|
||||
store(mask ^ bittab[n]);
|
||||
|
||||
break;
|
||||
|
||||
case '*': /* match 0 or more.. */
|
||||
case '+': /* match 1 or more.. */
|
||||
if (p == pat)
|
||||
return badpat("Empty closure");
|
||||
lp = sp; /* previous opcode */
|
||||
if (*lp == CLO) /* equivalence.. */
|
||||
break;
|
||||
switch(*lp) {
|
||||
|
||||
case BOL:
|
||||
case BOT:
|
||||
case EOT:
|
||||
case BOW:
|
||||
case EOW:
|
||||
case REF:
|
||||
return badpat("Illegal closure");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p == '+')
|
||||
for (sp = mp; lp < sp; lp++)
|
||||
store(*lp);
|
||||
|
||||
store(END);
|
||||
store(END);
|
||||
sp = mp;
|
||||
while (--mp > lp)
|
||||
*mp = mp[-1];
|
||||
store(CLO);
|
||||
mp = sp;
|
||||
break;
|
||||
|
||||
case '\\': /* tags, backrefs .. */
|
||||
switch(*++p) {
|
||||
|
||||
case '(':
|
||||
if (tagc < MAXTAG) {
|
||||
tagstk[++tagi] = tagc;
|
||||
store(BOT);
|
||||
store(tagc++);
|
||||
}
|
||||
else
|
||||
return badpat("Too many \\(\\) pairs");
|
||||
break;
|
||||
case ')':
|
||||
if (*sp == BOT)
|
||||
return badpat("Null pattern inside \\(\\)");
|
||||
if (tagi > 0) {
|
||||
store(EOT);
|
||||
store(tagstk[tagi--]);
|
||||
}
|
||||
else
|
||||
return badpat("Unmatched \\)");
|
||||
break;
|
||||
case '<':
|
||||
store(BOW);
|
||||
break;
|
||||
case '>':
|
||||
if (*sp == BOW)
|
||||
return badpat("Null pattern inside \\<\\>");
|
||||
store(EOW);
|
||||
break;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
n = *p-'0';
|
||||
if (tagi > 0 && tagstk[tagi] == n)
|
||||
return badpat("Cyclical reference");
|
||||
if (tagc > n) {
|
||||
store(REF);
|
||||
store(n);
|
||||
}
|
||||
else
|
||||
return badpat("Undetermined reference");
|
||||
break;
|
||||
#ifdef EXTEND
|
||||
case 'b':
|
||||
store(CHR);
|
||||
store('\b');
|
||||
break;
|
||||
case 'n':
|
||||
store(CHR);
|
||||
store('\n');
|
||||
break;
|
||||
case 'f':
|
||||
store(CHR);
|
||||
store('\f');
|
||||
break;
|
||||
case 'r':
|
||||
store(CHR);
|
||||
store('\r');
|
||||
break;
|
||||
case 't':
|
||||
store(CHR);
|
||||
store('\t');
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
store(CHR);
|
||||
store(*p);
|
||||
}
|
||||
break;
|
||||
|
||||
default : /* an ordinary char */
|
||||
store(CHR);
|
||||
store(*p);
|
||||
break;
|
||||
}
|
||||
sp = lp;
|
||||
}
|
||||
if (tagi > 0)
|
||||
return badpat("Unmatched \\(");
|
||||
store(END);
|
||||
sta = OKP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char *bol;
|
||||
char *bopat[MAXTAG];
|
||||
char *eopat[MAXTAG];
|
||||
#ifdef NEEDPROTOS
|
||||
static char *pmatch( char *lp, CHAR *ap );
|
||||
#else /* NEEDPROTOS */
|
||||
static char *pmatch();
|
||||
#endif /* NEEDPROTOS */
|
||||
|
||||
/*
|
||||
* re_exec:
|
||||
* execute nfa to find a match.
|
||||
*
|
||||
* special cases: (nfa[0])
|
||||
* BOL
|
||||
* Match only once, starting from the
|
||||
* beginning.
|
||||
* CHR
|
||||
* First locate the character without
|
||||
* calling pmatch, and if found, call
|
||||
* pmatch for the remaining string.
|
||||
* END
|
||||
* re_comp failed, poor luser did not
|
||||
* check for it. Fail fast.
|
||||
*
|
||||
* If a match is found, bopat[0] and eopat[0] are set
|
||||
* to the beginning and the end of the matched fragment,
|
||||
* respectively.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
re_exec( char *lp )
|
||||
{
|
||||
register char c;
|
||||
register char *ep = 0;
|
||||
register CHAR *ap = nfa;
|
||||
|
||||
bol = lp;
|
||||
|
||||
bopat[0] = 0;
|
||||
bopat[1] = 0;
|
||||
bopat[2] = 0;
|
||||
bopat[3] = 0;
|
||||
bopat[4] = 0;
|
||||
bopat[5] = 0;
|
||||
bopat[6] = 0;
|
||||
bopat[7] = 0;
|
||||
bopat[8] = 0;
|
||||
bopat[9] = 0;
|
||||
|
||||
switch(*ap) {
|
||||
|
||||
case BOL: /* anchored: match from BOL only */
|
||||
ep = pmatch(lp,ap);
|
||||
break;
|
||||
case CHR: /* ordinary char: locate it fast */
|
||||
c = *(ap+1);
|
||||
while (*lp && *lp != c)
|
||||
lp++;
|
||||
if (!*lp) /* if EOS, fail, else fall thru. */
|
||||
return 0;
|
||||
default: /* regular matching all the way. */
|
||||
do {
|
||||
if ((ep = pmatch(lp,ap)))
|
||||
break;
|
||||
lp++;
|
||||
} while (*lp);
|
||||
|
||||
break;
|
||||
case END: /* munged automaton. fail always */
|
||||
return 0;
|
||||
}
|
||||
if (!ep)
|
||||
return 0;
|
||||
|
||||
bopat[0] = lp;
|
||||
eopat[0] = ep;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pmatch: internal routine for the hard part
|
||||
*
|
||||
* This code is partly snarfed from an early grep written by
|
||||
* David Conroy. The backref and tag stuff, and various other
|
||||
* innovations are by oz.
|
||||
*
|
||||
* special case optimizations: (nfa[n], nfa[n+1])
|
||||
* CLO ANY
|
||||
* We KNOW .* will match everything upto the
|
||||
* end of line. Thus, directly go to the end of
|
||||
* line, without recursive pmatch calls. As in
|
||||
* the other closure cases, the remaining pattern
|
||||
* must be matched by moving backwards on the
|
||||
* string recursively, to find a match for xy
|
||||
* (x is ".*" and y is the remaining pattern)
|
||||
* where the match satisfies the LONGEST match for
|
||||
* x followed by a match for y.
|
||||
* CLO CHR
|
||||
* We can again scan the string forward for the
|
||||
* single char and at the point of failure, we
|
||||
* execute the remaining nfa recursively, same as
|
||||
* above.
|
||||
*
|
||||
* At the end of a successful match, bopat[n] and eopat[n]
|
||||
* are set to the beginning and end of subpatterns matched
|
||||
* by tagged expressions (n = 1 to 9).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef re_fail
|
||||
extern void re_fail();
|
||||
#endif /* re_fail */
|
||||
|
||||
/*
|
||||
* character classification table for word boundary operators BOW
|
||||
* and EOW. the reason for not using ctype macros is that we can
|
||||
* let the user add into our own table. see re_modw. This table
|
||||
* is not in the bitset form, since we may wish to extend it in the
|
||||
* future for other character classifications.
|
||||
*
|
||||
* TRUE for 0-9 A-Z a-z _
|
||||
*/
|
||||
static char chrtyp[MAXCHR] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
#define inascii(x) (0177&(x))
|
||||
#define iswordc(x) chrtyp[inascii(x)]
|
||||
#define isinset(x,y) ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
|
||||
|
||||
/*
|
||||
* skip values for CLO XXX to skip past the closure
|
||||
*/
|
||||
|
||||
#define ANYSKIP 2 /* [CLO] ANY END ... */
|
||||
#define CHRSKIP 3 /* [CLO] CHR chr END ... */
|
||||
#define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */
|
||||
|
||||
static char *
|
||||
pmatch( char *lp, CHAR *ap)
|
||||
{
|
||||
register int op, c, n;
|
||||
register char *e; /* extra pointer for CLO */
|
||||
register char *bp; /* beginning of subpat.. */
|
||||
register char *ep; /* ending of subpat.. */
|
||||
char *are; /* to save the line ptr. */
|
||||
|
||||
while ((op = *ap++) != END)
|
||||
switch(op) {
|
||||
|
||||
case CHR:
|
||||
if (*lp++ != *ap++)
|
||||
return 0;
|
||||
break;
|
||||
case ANY:
|
||||
if (!*lp++)
|
||||
return 0;
|
||||
break;
|
||||
case CCL:
|
||||
c = *lp++;
|
||||
if (!isinset(ap,c))
|
||||
return 0;
|
||||
ap += BITBLK;
|
||||
break;
|
||||
case BOL:
|
||||
if (lp != bol)
|
||||
return 0;
|
||||
break;
|
||||
case EOL:
|
||||
if (*lp)
|
||||
return 0;
|
||||
break;
|
||||
case BOT:
|
||||
bopat[*ap++] = lp;
|
||||
break;
|
||||
case EOT:
|
||||
eopat[*ap++] = lp;
|
||||
break;
|
||||
case BOW:
|
||||
if (lp!=bol && iswordc(lp[-1]) || !iswordc(*lp))
|
||||
return 0;
|
||||
break;
|
||||
case EOW:
|
||||
if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
|
||||
return 0;
|
||||
break;
|
||||
case REF:
|
||||
n = *ap++;
|
||||
bp = bopat[n];
|
||||
ep = eopat[n];
|
||||
while (bp < ep)
|
||||
if (*bp++ != *lp++)
|
||||
return 0;
|
||||
break;
|
||||
case CLO:
|
||||
are = lp;
|
||||
switch(*ap) {
|
||||
|
||||
case ANY:
|
||||
while (*lp)
|
||||
lp++;
|
||||
n = ANYSKIP;
|
||||
break;
|
||||
case CHR:
|
||||
c = *(ap+1);
|
||||
while (*lp && c == *lp)
|
||||
lp++;
|
||||
n = CHRSKIP;
|
||||
break;
|
||||
case CCL:
|
||||
while ((c = *lp) && isinset(ap+1,c))
|
||||
lp++;
|
||||
n = CCLSKIP;
|
||||
break;
|
||||
default:
|
||||
re_fail("closure: bad nfa.", *ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ap += n;
|
||||
|
||||
while (lp >= are) {
|
||||
if (e = pmatch(lp, ap))
|
||||
return e;
|
||||
--lp;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
re_fail("re_exec: bad nfa.", op);
|
||||
return 0;
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
/*
|
||||
* re_modw:
|
||||
* add new characters into the word table to change re_exec's
|
||||
* understanding of what a word should look like. Note that we
|
||||
* only accept additions into the word definition.
|
||||
*
|
||||
* If the string parameter is 0 or null string, the table is
|
||||
* reset back to the default containing A-Z a-z 0-9 _. [We use
|
||||
* the compact bitset representation for the default table]
|
||||
*/
|
||||
|
||||
static CHAR deftab[16] = {
|
||||
0, 0, 0, 0, 0, 0, 0377, 003, 0376, 0377, 0377, 0207,
|
||||
0376, 0377, 0377, 007
|
||||
};
|
||||
|
||||
void
|
||||
re_modw( char *s )
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (!s || !*s) {
|
||||
for (i = 0; i < MAXCHR; i++)
|
||||
if (!isinset(deftab,i))
|
||||
iswordc(i) = 0;
|
||||
}
|
||||
else
|
||||
while(*s)
|
||||
iswordc(*s++) = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* re_subs:
|
||||
* substitute the matched portions of the src in dst.
|
||||
*
|
||||
* & substitute the entire matched pattern.
|
||||
*
|
||||
* \digit substitute a subpattern, with the given tag number.
|
||||
* Tags are numbered from 1 to 9. If the particular
|
||||
* tagged subpattern does not exist, null is substituted.
|
||||
*/
|
||||
int
|
||||
re_subs( char *src, char *dst)
|
||||
{
|
||||
register char c;
|
||||
register int pin;
|
||||
register char *bp;
|
||||
register char *ep;
|
||||
|
||||
if (!*src || !bopat[0])
|
||||
return 0;
|
||||
|
||||
while (c = *src++) {
|
||||
switch(c) {
|
||||
|
||||
case '&':
|
||||
pin = 0;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
c = *src++;
|
||||
if (c >= '0' && c <= '9') {
|
||||
pin = c - '0';
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
*dst++ = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((bp = bopat[pin]) && (ep = eopat[pin])) {
|
||||
while (*bp && bp < ep)
|
||||
*dst++ = *bp++;
|
||||
if (bp < ep)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*dst = (char) 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* symbolic - produce a symbolic dump of the nfa
|
||||
*/
|
||||
symbolic( char *s )
|
||||
{
|
||||
printf("pattern: %s\n", s);
|
||||
printf("nfacode:\n");
|
||||
nfadump(nfa);
|
||||
}
|
||||
|
||||
static
|
||||
nfadump( CHAR *ap)
|
||||
{
|
||||
register int n;
|
||||
|
||||
while (*ap != END)
|
||||
switch(*ap++) {
|
||||
case CLO:
|
||||
printf("CLOSURE");
|
||||
nfadump(ap);
|
||||
switch(*ap) {
|
||||
case CHR:
|
||||
n = CHRSKIP;
|
||||
break;
|
||||
case ANY:
|
||||
n = ANYSKIP;
|
||||
break;
|
||||
case CCL:
|
||||
n = CCLSKIP;
|
||||
break;
|
||||
}
|
||||
ap += n;
|
||||
break;
|
||||
case CHR:
|
||||
printf("\tCHR %c\n",*ap++);
|
||||
break;
|
||||
case ANY:
|
||||
printf("\tANY .\n");
|
||||
break;
|
||||
case BOL:
|
||||
printf("\tBOL -\n");
|
||||
break;
|
||||
case EOL:
|
||||
printf("\tEOL -\n");
|
||||
break;
|
||||
case BOT:
|
||||
printf("BOT: %d\n",*ap++);
|
||||
break;
|
||||
case EOT:
|
||||
printf("EOT: %d\n",*ap++);
|
||||
break;
|
||||
case BOW:
|
||||
printf("BOW\n");
|
||||
break;
|
||||
case EOW:
|
||||
printf("EOW\n");
|
||||
break;
|
||||
case REF:
|
||||
printf("REF: %d\n",*ap++);
|
||||
break;
|
||||
case CCL:
|
||||
printf("\tCCL [");
|
||||
for (n = 0; n < MAXCHR; n++)
|
||||
if (isinset(ap,(CHAR)n)) {
|
||||
if (n < ' ')
|
||||
printf("^%c", n ^ 0x040);
|
||||
else
|
||||
printf("%c", n);
|
||||
}
|
||||
printf("]\n");
|
||||
ap += BITBLK;
|
||||
break;
|
||||
default:
|
||||
printf("bad nfa. opcode %o\n", ap[-1]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* MACOS or DOS or NEED_BSDREGEX */
|
@ -21,7 +21,7 @@ OBJS = ldbm.o
|
||||
HDIR = ../../include
|
||||
|
||||
INCLUDES= -I$(HDIR)
|
||||
DEFINES = $(DEFS)
|
||||
DEFINES = $(DEFS) $(LDBMDEFS)
|
||||
|
||||
CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS)
|
||||
|
||||
|
@ -21,22 +21,23 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \
|
||||
attr.c entry.c config.c backend.c result.c operation.c \
|
||||
dn.c compare.c modify.c delete.c modrdn.c ch_malloc.c \
|
||||
value.c ava.c bind.c unbind.c abandon.c filterentry.c \
|
||||
phonetic.c regex.c acl.c str2filter.c aclparse.c init.c \
|
||||
phonetic.c acl.c str2filter.c aclparse.c init.c \
|
||||
detach.c strdup.c tempnam.c repl.c lock.c \
|
||||
schema.c schemaparse.c monitor.c configinfo.c
|
||||
OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \
|
||||
attr.o entry.o config.o backend.o result.o operation.o \
|
||||
dn.o compare.o modify.o delete.o modrdn.o ch_malloc.o \
|
||||
value.o ava.o bind.o unbind.o abandon.o filterentry.o \
|
||||
phonetic.o regex.o acl.o str2filter.o aclparse.o init.o \
|
||||
phonetic.o acl.o str2filter.o aclparse.o init.o \
|
||||
detach.o strdup.o tempnam.o repl.o lock.o \
|
||||
schema.o schemaparse.o monitor.o configinfo.o
|
||||
|
||||
INCLUDES= -I. -I$(HDIR) $(KRBINCLUDEFLAG)
|
||||
DEFINES = $(DEFS) $(LDAP_CRYPT) $(LDAP_TCP_WRAPPERS) $(SERVERDEFS)
|
||||
DEFINES = $(DEFS) $(SERVERDEFS)
|
||||
CFLAGS = $(INCLUDES) $(THREADSINCLUDE) $(DEFINES) $(ACFLAGS) $(THREADS)
|
||||
LDFLAGS = -L$(LDIR) $(KRBLIBFLAG)
|
||||
LIBS = $(KRBLIBS) -llber -lldbm -lavl -llthread -lldif $(THREADSLIB) \
|
||||
LIBS = $(KRBLIBS) -llber -lldbm -lavl -llthread -lldif \
|
||||
$(REGEXLIB) $(THREADSLIB) \
|
||||
$(LDBMLIB) $(LDAP_CRYPT_LIB) $(LDAP_TCP_WRAPPERS_LIB) $(ALIBS)
|
||||
|
||||
all: FORCE
|
||||
|
@ -6,15 +6,11 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#ifdef sunos5
|
||||
#include "regexpr.h"
|
||||
#else
|
||||
#include "regex.h"
|
||||
#endif
|
||||
#include <regex.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Attribute *attr_find();
|
||||
extern char *re_comp();
|
||||
extern struct acl *global_acl;
|
||||
extern int global_default_access;
|
||||
extern char *access2str();
|
||||
@ -26,7 +22,10 @@ struct acl *acl_get_applicable();
|
||||
|
||||
static int regex_matches();
|
||||
|
||||
extern pthread_mutex_t regex_mutex;
|
||||
static string_expand(char *newbuf, int bufsiz, char *pattern,
|
||||
char *match, regmatch_t *matches);
|
||||
|
||||
extern Entry * be_dn2entry(Backend *be, char *bdn, char **matched);
|
||||
|
||||
/*
|
||||
* access_allowed - check whether dn is allowed the requested access
|
||||
@ -51,15 +50,57 @@ access_allowed(
|
||||
int access
|
||||
)
|
||||
{
|
||||
int rc;
|
||||
struct acl *a;
|
||||
int rc;
|
||||
struct acl *a;
|
||||
char *edn;
|
||||
|
||||
regmatch_t matches[MAXREMATCHES];
|
||||
int i;
|
||||
int n;
|
||||
|
||||
if ( be == NULL ) {
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
a = acl_get_applicable( be, op, e, attr );
|
||||
rc = acl_access_allowed( a, be, conn, e, val, op, access );
|
||||
edn = dn_normalize_case( strdup( e->e_dn ) );
|
||||
Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: entry (%s) attr (%s)\n",
|
||||
e->e_dn, attr, 0 );
|
||||
|
||||
/* the lastmod attributes are ignored by ACL checking */
|
||||
if ( strcasecmp( attr, "modifiersname" ) == 0 ||
|
||||
strcasecmp( attr, "modifytimestamp" ) == 0 ||
|
||||
strcasecmp( attr, "creatorsname" ) == 0 ||
|
||||
strcasecmp( attr, "createtimestamp" ) == 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ACL, "LASTMOD attribute: %s access allowed\n",
|
||||
attr, 0, 0 );
|
||||
free( edn );
|
||||
return(1);
|
||||
}
|
||||
|
||||
memset(matches, 0, sizeof(matches));
|
||||
|
||||
a = acl_get_applicable( be, op, e, attr, edn, MAXREMATCHES, matches );
|
||||
|
||||
if (a) {
|
||||
for (i = 0; i < MAXREMATCHES && matches[i].rm_so > 0; i++) {
|
||||
Debug( LDAP_DEBUG_ARGS, "=> match[%d]: %d %d ",
|
||||
i, matches[i].rm_so, matches[i].rm_eo );
|
||||
|
||||
if( matches[i].rm_so <= matches[0].rm_eo ) {
|
||||
for ( n = matches[i].rm_so; n < matches[i].rm_eo; n++) {
|
||||
Debug( LDAP_DEBUG_ARGS, "%c", edn[n], 0, 0 );
|
||||
}
|
||||
}
|
||||
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
rc = acl_access_allowed( a, be, conn, e, val, op, access, edn, matches );
|
||||
free( edn );
|
||||
|
||||
Debug( LDAP_DEBUG_ACL, "\n=> access_allowed: exit (%s) attr (%s)\n",
|
||||
e->e_dn, attr, 0);
|
||||
|
||||
return( rc );
|
||||
}
|
||||
@ -75,15 +116,17 @@ acl_get_applicable(
|
||||
Backend *be,
|
||||
Operation *op,
|
||||
Entry *e,
|
||||
char *attr
|
||||
char *attr,
|
||||
char *edn,
|
||||
int nmatch,
|
||||
regmatch_t *matches
|
||||
)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
struct acl *a;
|
||||
char *edn;
|
||||
|
||||
Debug( LDAP_DEBUG_ACL, "=> acl_get: entry (%s) attr (%s)\n", e->e_dn,
|
||||
attr, 0 );
|
||||
Debug( LDAP_DEBUG_ACL, "\n=> acl_get: entry (%s) attr (%s)\n",
|
||||
e->e_dn, attr, 0 );
|
||||
|
||||
if ( be_isroot( be, op->o_dn ) ) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
@ -92,55 +135,73 @@ acl_get_applicable(
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "=> acl_get: edn %s\n", edn, 0, 0 );
|
||||
|
||||
/* check for a backend-specific acl that matches the entry */
|
||||
for ( i = 1, a = be->be_acl; a != NULL; a = a->acl_next, i++ ) {
|
||||
if ( a->acl_dnpat != NULL ) {
|
||||
edn = dn_normalize_case( strdup( e->e_dn ) );
|
||||
if ( ! regex_matches( a->acl_dnpat, edn ) ) {
|
||||
free( edn );
|
||||
if (a->acl_dnpat != NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n",
|
||||
i, a->acl_dnpat, a->acl_dnre.re_nsub);
|
||||
|
||||
if (regexec(&a->acl_dnre, edn, nmatch, matches, 0))
|
||||
continue;
|
||||
}
|
||||
free( edn );
|
||||
else
|
||||
Debug( LDAP_DEBUG_TRACE, "=> acl_get:[%d] backend ACL match\n",
|
||||
i, 0, 0);
|
||||
}
|
||||
|
||||
if ( a->acl_filter != NULL ) {
|
||||
if ( test_filter( NULL, NULL, NULL, e, a->acl_filter )
|
||||
!= 0 ) {
|
||||
if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr %s\n", i, attr, 0);
|
||||
|
||||
if ( attr == NULL || a->acl_attrs == NULL ||
|
||||
charray_inlist( a->acl_attrs, attr ) ) {
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl_get: backend acl #%d\n",
|
||||
i, e->e_dn, attr );
|
||||
charray_inlist( a->acl_attrs, attr ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] backend acl %s attr: %s\n",
|
||||
i, e->e_dn, attr );
|
||||
return( a );
|
||||
}
|
||||
matches[0].rm_so = matches[0].rm_eo = -1;
|
||||
}
|
||||
|
||||
/* check for a global acl that matches the entry */
|
||||
for ( i = 1, a = global_acl; a != NULL; a = a->acl_next, i++ ) {
|
||||
if ( a->acl_dnpat != NULL ) {
|
||||
edn = dn_normalize_case( strdup( e->e_dn ) );
|
||||
if ( ! regex_matches( a->acl_dnpat, edn ) ) {
|
||||
free( edn );
|
||||
if (a->acl_dnpat != NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "=> dnpat: [%d] %s nsub: %d\n",
|
||||
i, a->acl_dnpat, a->acl_dnre.re_nsub);
|
||||
|
||||
if (regexec(&a->acl_dnre, edn, nmatch, matches, 0)) {
|
||||
continue;
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE, "=> acl_get: [%d] global ACL match\n",
|
||||
i, 0, 0);
|
||||
}
|
||||
free( edn );
|
||||
}
|
||||
|
||||
if ( a->acl_filter != NULL ) {
|
||||
if ( test_filter( NULL, NULL, NULL, e, a->acl_filter )
|
||||
!= 0 ) {
|
||||
if ( test_filter( NULL, NULL, NULL, e, a->acl_filter ) != 0 ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( attr == NULL || a->acl_attrs == NULL || charray_inlist(
|
||||
a->acl_attrs, attr ) ) {
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl_get: global acl #%d\n",
|
||||
i, e->e_dn, attr );
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "=> acl_get: [%d] check attr\n", i, 0, 0);
|
||||
|
||||
if ( attr == NULL || a->acl_attrs == NULL ||
|
||||
charray_inlist( a->acl_attrs, attr ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl_get: [%d] global acl %s attr: %s\n",
|
||||
i, e->e_dn, attr );
|
||||
return( a );
|
||||
}
|
||||
}
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 );
|
||||
|
||||
matches[0].rm_so = matches[0].rm_eo = -1;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 );
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
@ -161,31 +222,40 @@ acl_access_allowed(
|
||||
Entry *e,
|
||||
struct berval *val,
|
||||
Operation *op,
|
||||
int access
|
||||
int access,
|
||||
char *edn,
|
||||
regmatch_t *matches
|
||||
)
|
||||
{
|
||||
int i;
|
||||
char *edn, *odn;
|
||||
char *odn;
|
||||
struct access *b;
|
||||
Attribute *at;
|
||||
struct berval bv;
|
||||
int default_access;
|
||||
|
||||
Debug( LDAP_DEBUG_ACL, "=> acl: %s access to value \"%s\" by \"%s\"\n",
|
||||
access2str( access ), val ? val->bv_val : "any", op->o_dn ?
|
||||
op->o_dn : "" );
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"\n=> acl_access_allowed: %s access to entry \"%s\"\n",
|
||||
access2str( access ), e->e_dn, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"\n=> acl_access_allowed: %s access to value \"%s\" by \"%s\"\n",
|
||||
access2str( access ),
|
||||
val ? val->bv_val : "any",
|
||||
op->o_dn ? op->o_dn : "" );
|
||||
|
||||
if ( be_isroot( be, op->o_dn ) ) {
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl: granted to database root\n",
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl_access_allowed: granted to database root\n",
|
||||
0, 0, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
default_access = be->be_dfltaccess ? be->be_dfltaccess :
|
||||
global_default_access;
|
||||
default_access = be->be_dfltaccess ? be->be_dfltaccess : global_default_access;
|
||||
|
||||
if ( a == NULL ) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl: %s by default (no matching to)\n",
|
||||
"<= acl_access_allowed: %s by default (no matching to)\n",
|
||||
default_access >= access ? "granted" : "denied", 0, 0 );
|
||||
return( default_access >= access );
|
||||
}
|
||||
@ -198,76 +268,78 @@ acl_access_allowed(
|
||||
}
|
||||
for ( i = 1, b = a->acl_access; b != NULL; b = b->a_next, i++ ) {
|
||||
if ( b->a_dnpat != NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "<= check a_dnpat: %s\n",
|
||||
b->a_dnpat, 0, 0);
|
||||
/*
|
||||
* if access applies to the entry itself, and the
|
||||
* user is bound as somebody in the same namespace as
|
||||
* the entry, OR the given dn matches the dn pattern
|
||||
*/
|
||||
if ( strcasecmp( b->a_dnpat, "self" ) == 0 && op->o_dn
|
||||
!= NULL && *(op->o_dn) && e->e_dn != NULL ) {
|
||||
edn = dn_normalize_case( strdup( e->e_dn ) );
|
||||
if ( strcasecmp( b->a_dnpat, "self" ) == 0 &&
|
||||
op->o_dn != NULL && *(op->o_dn) && e->e_dn != NULL )
|
||||
{
|
||||
if ( strcasecmp( edn, op->o_dn ) == 0 ) {
|
||||
free( edn );
|
||||
if ( odn ) free( odn );
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl: matched by clause #%d access %s\n",
|
||||
"<= acl_access_allowed: matched by clause #%d access %s\n",
|
||||
i, (b->a_access & ~ACL_SELF) >=
|
||||
access ? "granted" : "denied", 0 );
|
||||
|
||||
return( (b->a_access & ~ACL_SELF)
|
||||
>= access );
|
||||
}
|
||||
free( edn );
|
||||
} else {
|
||||
if ( regex_matches( b->a_dnpat, odn ) ) {
|
||||
if ( odn ) free( odn );
|
||||
return( (b->a_access & ~ACL_SELF) >= access );
|
||||
}
|
||||
} else {
|
||||
if ( regex_matches( b->a_dnpat, odn, edn, matches ) ) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl: matched by clause #%d access %s\n",
|
||||
"<= acl_access_allowed: matched by clause #%d access %s\n",
|
||||
i, (b->a_access & ~ACL_SELF) >= access ?
|
||||
"granted" : "denied", 0 );
|
||||
|
||||
return( (b->a_access & ~ACL_SELF)
|
||||
>= access );
|
||||
if ( odn ) free( odn );
|
||||
return( (b->a_access & ~ACL_SELF) >= access );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( b->a_addrpat != NULL ) {
|
||||
if ( regex_matches( b->a_addrpat, conn->c_addr ) ) {
|
||||
if ( odn ) free( odn );
|
||||
if ( regex_matches( b->a_addrpat, conn->c_addr, edn, matches ) ) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl: matched by clause #%d access %s\n",
|
||||
"<= acl_access_allowed: matched by clause #%d access %s\n",
|
||||
i, (b->a_access & ~ACL_SELF) >= access ?
|
||||
"granted" : "denied", 0 );
|
||||
|
||||
if ( odn ) free( odn );
|
||||
return( (b->a_access & ~ACL_SELF) >= access );
|
||||
}
|
||||
}
|
||||
if ( b->a_domainpat != NULL ) {
|
||||
if ( regex_matches( b->a_domainpat, conn->c_domain ) ) {
|
||||
if ( odn ) free( odn );
|
||||
Debug( LDAP_DEBUG_ARGS, "<= check a_domainpath: %s\n",
|
||||
b->a_domainpat, 0, 0 );
|
||||
if ( regex_matches( b->a_domainpat, conn->c_domain, edn, matches ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl: matched by clause #%d access %s\n",
|
||||
"<= acl_access_allowed: matched by clause #%d access %s\n",
|
||||
i, (b->a_access & ~ACL_SELF) >= access ?
|
||||
"granted" : "denied", 0 );
|
||||
|
||||
if ( odn ) free( odn );
|
||||
return( (b->a_access & ~ACL_SELF) >= access );
|
||||
}
|
||||
}
|
||||
if ( b->a_dnattr != NULL && op->o_dn != NULL ) {
|
||||
Debug( LDAP_DEBUG_ARGS, "<= check a_dnattr: %s\n",
|
||||
b->a_dnattr, 0, 0);
|
||||
/* see if asker is listed in dnattr */
|
||||
if ( (at = attr_find( e->e_attrs, b->a_dnattr ))
|
||||
!= NULL && value_find( at->a_vals, &bv,
|
||||
at->a_syntax, 3 ) == 0 )
|
||||
if ( (at = attr_find( e->e_attrs, b->a_dnattr )) != NULL &&
|
||||
value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 )
|
||||
{
|
||||
if ( (b->a_access & ACL_SELF) && (val == NULL
|
||||
|| value_cmp( &bv, val, at->a_syntax,
|
||||
2 )) ) {
|
||||
if ( (b->a_access & ACL_SELF) &&
|
||||
(val == NULL || value_cmp( &bv, val, at->a_syntax, 2 )) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( odn ) free( odn );
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl: matched by clause #%d access %s\n",
|
||||
"<= acl_acces_allowed: matched by clause #%d access %s\n",
|
||||
i, (b->a_access & ~ACL_SELF) >= access ?
|
||||
"granted" : "denied", 0 );
|
||||
|
||||
@ -276,22 +348,49 @@ acl_access_allowed(
|
||||
|
||||
/* asker not listed in dnattr - check for self access */
|
||||
if ( ! (b->a_access & ACL_SELF) || val == NULL ||
|
||||
value_cmp( &bv, val, at->a_syntax, 2 ) != 0 ) {
|
||||
value_cmp( &bv, val, at->a_syntax, 2 ) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( odn ) free( odn );
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl: matched by clause #%d (self) access %s\n",
|
||||
"<= acl_access_allowed: matched by clause #%d (self) access %s\n",
|
||||
i, (b->a_access & ~ACL_SELF) >= access ? "granted"
|
||||
: "denied", 0 );
|
||||
|
||||
return( (b->a_access & ~ACL_SELF) >= access );
|
||||
}
|
||||
#ifdef ACLGROUP
|
||||
if ( b->a_group != NULL && op->o_dn != NULL ) {
|
||||
char buf[512];
|
||||
|
||||
/* b->a_group is an unexpanded entry name, expanded it should be an
|
||||
* entry with objectclass group* and we test to see if odn is one of
|
||||
* the values in the attribute uniquegroup
|
||||
*/
|
||||
Debug( LDAP_DEBUG_ARGS, "<= check a_group: %s\n",
|
||||
b->a_group, 0, 0);
|
||||
Debug( LDAP_DEBUG_ARGS, "<= check a_group: odn: %s\n",
|
||||
odn, 0, 0);
|
||||
|
||||
/* see if asker is listed in dnattr */
|
||||
string_expand(buf, sizeof(buf), b->a_group, edn, matches);
|
||||
|
||||
if (be_group(be, buf, odn) == 0) {
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl_access_allowed: matched by clause #%d (group) access granted\n",
|
||||
i, 0, 0 );
|
||||
if ( odn ) free( odn );
|
||||
return( (b->a_access & ~ACL_SELF) >= access );
|
||||
}
|
||||
}
|
||||
#endif /* ACLGROUP */
|
||||
}
|
||||
|
||||
if ( odn ) free( odn );
|
||||
Debug( LDAP_DEBUG_ACL, "<= acl: %s by default (no matching by)\n",
|
||||
Debug( LDAP_DEBUG_ACL,
|
||||
"<= acl_access_allowed: %s by default (no matching by)\n",
|
||||
default_access >= access ? "granted" : "denied", 0, 0 );
|
||||
|
||||
return( default_access >= access );
|
||||
@ -316,14 +415,26 @@ acl_check_mods(
|
||||
{
|
||||
int i;
|
||||
struct acl *a;
|
||||
char *edn;
|
||||
|
||||
edn = dn_normalize_case( strdup( e->e_dn ) );
|
||||
|
||||
for ( ; mods != NULL; mods = mods->mod_next ) {
|
||||
regmatch_t matches[MAXREMATCHES];
|
||||
|
||||
/* the lastmod attributes are ignored by ACL checking */
|
||||
if ( strcasecmp( mods->mod_type, "modifiersname" ) == 0 ||
|
||||
strcasecmp( mods->mod_type, "modifytimestamp" ) == 0 ) {
|
||||
strcasecmp( mods->mod_type, "modifytimestamp" ) == 0 ||
|
||||
strcasecmp( mods->mod_type, "creatorsname" ) == 0 ||
|
||||
strcasecmp( mods->mod_type, "createtimestamp" ) == 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ACL, "LASTMOD attribute: %s access allowed\n",
|
||||
mods->mod_type, 0, 0 );
|
||||
continue;
|
||||
}
|
||||
|
||||
a = acl_get_applicable( be, op, e, mods->mod_type );
|
||||
a = acl_get_applicable( be, op, e, mods->mod_type, edn,
|
||||
MAXREMATCHES, matches );
|
||||
|
||||
switch ( mods->mod_op & ~LDAP_MOD_BVALUES ) {
|
||||
case LDAP_MOD_REPLACE:
|
||||
@ -332,8 +443,10 @@ acl_check_mods(
|
||||
break;
|
||||
}
|
||||
for ( i = 0; mods->mod_bvalues[i] != NULL; i++ ) {
|
||||
if ( ! acl_access_allowed( a, be, conn, e,
|
||||
mods->mod_bvalues[i], op, ACL_WRITE ) ) {
|
||||
if ( ! acl_access_allowed( a, be, conn, e, mods->mod_bvalues[i],
|
||||
op, ACL_WRITE, edn, matches) )
|
||||
{
|
||||
free(edn);
|
||||
return( LDAP_INSUFFICIENT_ACCESS );
|
||||
}
|
||||
}
|
||||
@ -342,14 +455,18 @@ acl_check_mods(
|
||||
case LDAP_MOD_DELETE:
|
||||
if ( mods->mod_bvalues == NULL ) {
|
||||
if ( ! acl_access_allowed( a, be, conn, e,
|
||||
NULL, op, ACL_WRITE ) ) {
|
||||
NULL, op, ACL_WRITE, edn, matches) )
|
||||
{
|
||||
free(edn);
|
||||
return( LDAP_INSUFFICIENT_ACCESS );
|
||||
}
|
||||
break;
|
||||
}
|
||||
for ( i = 0; mods->mod_bvalues[i] != NULL; i++ ) {
|
||||
if ( ! acl_access_allowed( a, be, conn, e,
|
||||
mods->mod_bvalues[i], op, ACL_WRITE ) ) {
|
||||
if ( ! acl_access_allowed( a, be, conn, e, mods->mod_bvalues[i],
|
||||
op, ACL_WRITE, edn, matches) )
|
||||
{
|
||||
free(edn);
|
||||
return( LDAP_INSUFFICIENT_ACCESS );
|
||||
}
|
||||
}
|
||||
@ -357,48 +474,95 @@ acl_check_mods(
|
||||
}
|
||||
}
|
||||
|
||||
free(edn);
|
||||
return( LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
#ifdef sunos5
|
||||
|
||||
static int
|
||||
regex_matches( char *pat, char *str )
|
||||
static string_expand(
|
||||
char *newbuf,
|
||||
int bufsiz,
|
||||
char *pat,
|
||||
char *match,
|
||||
regmatch_t *matches)
|
||||
{
|
||||
char *e;
|
||||
int rc;
|
||||
int size;
|
||||
char *sp;
|
||||
char *dp;
|
||||
int flag;
|
||||
|
||||
if ( (e = compile( pat, NULL, NULL )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"compile( \"%s\", \"%s\") failed\n", pat, str, 0 );
|
||||
return( 0 );
|
||||
size = 0;
|
||||
newbuf[0] = '\0';
|
||||
|
||||
flag = 0;
|
||||
for ( dp = newbuf, sp = pat; size < 512 && *sp ; sp++) {
|
||||
/* did we previously see a $ */
|
||||
if (flag) {
|
||||
if (*sp == '$') {
|
||||
*dp++ = '$';
|
||||
size++;
|
||||
} else if (*sp >= '0' && *sp <= '9' ) {
|
||||
int n;
|
||||
int i;
|
||||
char *ep;
|
||||
int l;
|
||||
|
||||
n = *sp - '0';
|
||||
*dp = '\0';
|
||||
i = matches[n].rm_so;
|
||||
l = matches[n].rm_eo;
|
||||
for ( ; size < 512 && i < l; size++, i++ ) {
|
||||
*dp++ = match[i];
|
||||
size++;
|
||||
}
|
||||
*dp = '\0';
|
||||
}
|
||||
flag = 0;
|
||||
} else {
|
||||
if (*sp == '$') {
|
||||
flag = 1;
|
||||
} else {
|
||||
*dp++ = *sp;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
rc = step( str ? str : "", e );
|
||||
free( e );
|
||||
*dp = '\0';
|
||||
|
||||
return( rc );
|
||||
Debug( LDAP_DEBUG_TRACE, "=> string_expand: pattern: %s\n", pat, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "=> string_expand: expanded: %s\n", newbuf, 0, 0 );
|
||||
}
|
||||
|
||||
#else /* sunos5 */
|
||||
|
||||
static int
|
||||
regex_matches( char *pat, char *str )
|
||||
regex_matches(
|
||||
char *pat, /* pattern to expand and match against */
|
||||
char *str, /* string to match against pattern */
|
||||
char *buf, /* buffer with $N expansion variables */
|
||||
regmatch_t *matches /* offsets in buffer for $N expansion variables */
|
||||
)
|
||||
{
|
||||
char *e;
|
||||
regex_t re;
|
||||
char newbuf[512];
|
||||
int rc;
|
||||
|
||||
pthread_mutex_lock( ®ex_mutex );
|
||||
if ( (e = re_comp( pat )) != NULL ) {
|
||||
string_expand(newbuf, sizeof(newbuf), pat, buf, matches);
|
||||
if (( rc = regcomp(&re, newbuf, REG_EXTENDED|REG_ICASE))) {
|
||||
char error[512];
|
||||
regerror(rc, &re, error, sizeof(error));
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"re_comp( \"%s\", \"%s\") failed because (%s)\n", pat, str,
|
||||
e );
|
||||
pthread_mutex_unlock( ®ex_mutex );
|
||||
"compile( \"%s\", \"%s\") failed %s\n",
|
||||
pat, str, error );
|
||||
return( 0 );
|
||||
}
|
||||
rc = re_exec( str ? str : "" );
|
||||
pthread_mutex_unlock( ®ex_mutex );
|
||||
|
||||
return( rc == 1 );
|
||||
rc = regexec(&re, str, 0, NULL, 0);
|
||||
regfree( &re );
|
||||
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> regex_matches: string: %s\n", str, 0, 0 );
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"=> regex_matches: rc: %d %s\n",
|
||||
rc, !rc ? "matches" : "no matches", 0 );
|
||||
return( !rc );
|
||||
}
|
||||
|
||||
#endif /* sunos5 */
|
||||
|
@ -7,12 +7,13 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include "regex.h"
|
||||
#include <unistd.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "portable.h"
|
||||
|
||||
extern Filter *str2filter();
|
||||
extern char *re_comp();
|
||||
extern struct acl *global_acl;
|
||||
extern char **str2charray();
|
||||
extern char *dn_upcase();
|
||||
@ -26,6 +27,62 @@ static void print_acl();
|
||||
static void print_access();
|
||||
#endif
|
||||
|
||||
int
|
||||
regtest(char *fname, int lineno, char *pat) {
|
||||
int e;
|
||||
regex_t re;
|
||||
|
||||
char buf[512];
|
||||
int size;
|
||||
|
||||
char *sp;
|
||||
char *dp;
|
||||
int flag;
|
||||
|
||||
sp = pat;
|
||||
dp = buf;
|
||||
size = 0;
|
||||
buf[0] = '\0';
|
||||
|
||||
for (size = 0, flag = 0; (size < sizeof(buf)) && *sp; sp++) {
|
||||
if (flag) {
|
||||
if (*sp == '$'|| (*sp >= '0' && *sp <= '9')) {
|
||||
*dp++ = *sp;
|
||||
size++;
|
||||
}
|
||||
flag = 0;
|
||||
|
||||
} else {
|
||||
if (*sp == '$') {
|
||||
flag = 1;
|
||||
} else {
|
||||
*dp++ = *sp;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*dp = '\0';
|
||||
if ( size >= (sizeof(buf)-1) ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: regular expression \"%s\" too large\n",
|
||||
fname, lineno, pat, 0 );
|
||||
acl_usage();
|
||||
}
|
||||
|
||||
if ((e = regcomp(&re, buf, REG_EXTENDED|REG_ICASE))) {
|
||||
char error[512];
|
||||
regerror(e, &re, error, sizeof(error));
|
||||
fprintf( stderr,
|
||||
"%s: line %d: regular expression \"%s\" bad because of %s\n",
|
||||
fname, lineno, pat, error );
|
||||
acl_usage();
|
||||
return(0);
|
||||
}
|
||||
regfree(&re);
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
parse_acl(
|
||||
Backend *be,
|
||||
@ -58,6 +115,17 @@ parse_acl(
|
||||
}
|
||||
|
||||
if ( strcasecmp( argv[i], "*" ) == 0 ) {
|
||||
int e;
|
||||
if ((e = regcomp( &a->acl_dnre, ".*",
|
||||
REG_EXTENDED|REG_ICASE)))
|
||||
{
|
||||
char buf[512];
|
||||
regerror(e, &a->acl_dnre, buf, sizeof(buf));
|
||||
fprintf( stderr,
|
||||
"%s: line %d: regular expression \"%s\" bad because of %s\n",
|
||||
fname, lineno, right, buf );
|
||||
acl_usage();
|
||||
}
|
||||
a->acl_dnpat = strdup( ".*" );
|
||||
continue;
|
||||
}
|
||||
@ -79,14 +147,19 @@ parse_acl(
|
||||
acl_usage();
|
||||
}
|
||||
} else if ( strcasecmp( left, "dn" ) == 0 ) {
|
||||
if ( (e = re_comp( right )) != NULL ) {
|
||||
int e;
|
||||
if ((e = regcomp(&a->acl_dnre, right,
|
||||
REG_EXTENDED|REG_ICASE))) {
|
||||
char buf[512];
|
||||
regerror(e, &a->acl_dnre, buf, sizeof(buf));
|
||||
fprintf( stderr,
|
||||
"%s: line %d: regular expression \"%s\" bad because of %s\n",
|
||||
fname, lineno, right, e );
|
||||
"%s: line %d: regular expression \"%s\" bad because of %s\n",
|
||||
fname, lineno, right, buf );
|
||||
acl_usage();
|
||||
|
||||
} else {
|
||||
a->acl_dnpat = dn_upcase(strdup( right ));
|
||||
}
|
||||
a->acl_dnpat = dn_upcase( strdup(
|
||||
right ) );
|
||||
} else if ( strncasecmp( left, "attr", 4 )
|
||||
== 0 ) {
|
||||
char **alist;
|
||||
@ -96,7 +169,7 @@ parse_acl(
|
||||
free( alist );
|
||||
} else {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: expecting <what> got \"%s\"\n",
|
||||
"%s: line %d: expecting <what> got \"%s\"\n",
|
||||
fname, lineno, left );
|
||||
acl_usage();
|
||||
}
|
||||
@ -106,7 +179,7 @@ parse_acl(
|
||||
} else if ( strcasecmp( argv[i], "by" ) == 0 ) {
|
||||
if ( a == NULL ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: to clause required before by clause in access line\n",
|
||||
"%s: line %d: to clause required before by clause in access line\n",
|
||||
fname, lineno );
|
||||
acl_usage();
|
||||
}
|
||||
@ -131,38 +204,27 @@ parse_acl(
|
||||
} else if ( strcasecmp( argv[i], "self" ) == 0 ) {
|
||||
b->a_dnpat = strdup( "self" );
|
||||
} else if ( strcasecmp( left, "dn" ) == 0 ) {
|
||||
if ( (e = re_comp( right )) != NULL ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: regular expression \"%s\" bad: %s\n",
|
||||
fname, lineno, right, e );
|
||||
acl_usage();
|
||||
}
|
||||
regtest(fname, lineno, right);
|
||||
b->a_dnpat = dn_upcase( strdup( right ) );
|
||||
} else if ( strcasecmp( left, "dnattr" )
|
||||
== 0 ) {
|
||||
} else if ( strcasecmp( left, "dnattr" ) == 0 ) {
|
||||
b->a_dnattr = strdup( right );
|
||||
} else if ( strcasecmp( left, "domain" )
|
||||
== 0 ) {
|
||||
char *s;
|
||||
|
||||
if ( (e = re_comp( right )) != NULL ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: regular expression \"%s\" bad: %s\n",
|
||||
fname, lineno, right, e );
|
||||
acl_usage();
|
||||
}
|
||||
#ifdef ACLGROUP
|
||||
} else if ( strcasecmp( left, "group" ) == 0 ) {
|
||||
regtest(fname, lineno, right);
|
||||
b->a_group = dn_upcase(strdup( right ));
|
||||
#endif /* ACLGROUP */
|
||||
} else if ( strcasecmp( left, "domain" ) == 0 ) {
|
||||
char *s;
|
||||
regtest(fname, lineno, right);
|
||||
b->a_domainpat = strdup( right );
|
||||
|
||||
/* normalize the domain */
|
||||
for ( s = b->a_domainpat; *s; s++ ) {
|
||||
*s = TOLOWER( *s );
|
||||
}
|
||||
} else if ( strcasecmp( left, "addr" ) == 0 ) {
|
||||
if ( (e = re_comp( right )) != NULL ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: regular expression \"%s\" bad: %s\n",
|
||||
fname, lineno, right, e );
|
||||
acl_usage();
|
||||
}
|
||||
regtest(fname, lineno, right);
|
||||
b->a_addrpat = strdup( right );
|
||||
} else {
|
||||
fprintf( stderr,
|
||||
@ -198,16 +260,15 @@ parse_acl(
|
||||
|
||||
/* if we have no real access clause, complain and do nothing */
|
||||
if ( a == NULL ) {
|
||||
|
||||
fprintf( stderr,
|
||||
"%s: line %d: warning: no access clause(s) specified in access line\n",
|
||||
"%s: line %d: warning: no access clause(s) specified in access line\n",
|
||||
fname, lineno );
|
||||
|
||||
} else {
|
||||
|
||||
if ( a->acl_access == NULL ) {
|
||||
fprintf( stderr,
|
||||
"%s: line %d: warning: no by clause(s) specified in access line\n",
|
||||
"%s: line %d: warning: no by clause(s) specified in access line\n",
|
||||
fname, lineno );
|
||||
}
|
||||
|
||||
@ -373,4 +434,4 @@ print_acl( struct acl *a )
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* LDAP_DEBUG */
|
||||
|
@ -20,14 +20,14 @@ VERSIONFILE = $(LDAPSRC)/build/version
|
||||
SRCS = idl.c add.c search.c cache.c dbcache.c dn2id.c id2entry.c \
|
||||
index.c id2children.c nextid.c abandon.c compare.c \
|
||||
modify.c modrdn.c delete.c init.c config.c bind.c attr.c \
|
||||
filterindex.c unbind.c kerberos.c close.c
|
||||
filterindex.c unbind.c kerberos.c close.c group.c
|
||||
OBJS = idl.o add.o search.o cache.o dbcache.o dn2id.o id2entry.o \
|
||||
index.o id2children.o nextid.o abandon.o compare.o \
|
||||
modify.o modrdn.o delete.o init.o config.o bind.o attr.o \
|
||||
filterindex.o unbind.o kerberos.o close.o
|
||||
filterindex.o unbind.o kerberos.o close.o group.o
|
||||
|
||||
INCLUDES= -I. -I.. -I$(HDIR) $(KRBINCLUDEFLAG)
|
||||
DEFINES = $(DEFS) $(LDAP_CRYPT) $(THREADS)
|
||||
DEFINES = $(DEFS) $(SERVERDEFS) $(THREADS)
|
||||
CFLAGS = $(INCLUDES) $(THREADSINCLUDE) $(DEFINES) $(ACFLAGS)
|
||||
LDFLAGS = -L$(LDIR) $(KRBLIBFLAG) $(LDAP_CRYPT_LIB)
|
||||
|
||||
|
90
servers/slapd/back-ldbm/group.c
Normal file
90
servers/slapd/back-ldbm/group.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* compare.c - ldbm backend compare routine */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
extern Entry *dn2entry();
|
||||
extern Attribute *attr_find();
|
||||
|
||||
|
||||
#ifdef ACLGROUP
|
||||
/* return 0 IFF edn is a value in uniqueMember attribute
|
||||
* of entry with bdn AND that entry has an objectClass
|
||||
* value of groupOfUniqueNames
|
||||
*/
|
||||
int
|
||||
ldbm_back_group(
|
||||
Backend *be,
|
||||
char *bdn,
|
||||
char *edn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *e;
|
||||
char *matched;
|
||||
Attribute *objectClass;
|
||||
Attribute *uniqueMember;
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: bdn: %s\n", bdn, 0, 0 );
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: edn: %s\n", edn, 0, 0 );
|
||||
|
||||
/* can we find bdn entry */
|
||||
if ((e = dn2entry(be, bdn, &matched )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: cannot find bdn: %s matched: %x\n", bdn, matched, 0 );
|
||||
if (matched != NULL)
|
||||
free(matched);
|
||||
return( 1 );
|
||||
}
|
||||
Debug( LDAP_DEBUG_ARGS, "ldbm_back_group: found bdn: %s matched: %x\n", bdn, matched, 0 );
|
||||
|
||||
|
||||
/* find it's objectClass and uniqueMember attribute values
|
||||
* make sure this is a group entry
|
||||
* finally test if we can find edn in the uniqueMember attribute value list *
|
||||
*/
|
||||
|
||||
rc = 1;
|
||||
if ((objectClass = attr_find(e->e_attrs, "objectclass")) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: failed to find objectClass\n", 0, 0, 0 );
|
||||
}
|
||||
else if ((uniqueMember = attr_find(e->e_attrs, "uniquemember")) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: failed to find uniqueMember\n", 0, 0, 0 );
|
||||
}
|
||||
else {
|
||||
struct berval bvObjectClass;
|
||||
struct berval bvUniqueMembers;
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "ldbm_back_group: found objectClass and uniqueMembers\n", 0, 0, 0 );
|
||||
|
||||
bvObjectClass.bv_val = "groupofuniquenames";
|
||||
bvObjectClass.bv_len = strlen( bvObjectClass.bv_val );
|
||||
bvUniqueMembers.bv_val = edn;
|
||||
bvUniqueMembers.bv_len = strlen( edn );
|
||||
|
||||
if (value_find(objectClass->a_vals, &bvObjectClass, SYNTAX_CIS, 1) != 0) {
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: failed to find objectClass in groupOfUniqueNames\n",
|
||||
0, 0, 0 );
|
||||
}
|
||||
else if (value_find(uniqueMember->a_vals, &bvUniqueMembers, SYNTAX_CIS, 1) != 0) {
|
||||
Debug( LDAP_DEBUG_ACL, "ldbm_back_group: %s not in %s: groupOfUniqueNames\n",
|
||||
edn, bdn, 0 );
|
||||
}
|
||||
else {
|
||||
Debug( LDAP_DEBUG_ACL, "ldbm_back_group: %s is in %s: groupOfUniqueNames\n",
|
||||
edn, bdn, 0 );
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* free e */
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
Debug( LDAP_DEBUG_ARGS, "ldbm_back_group: rc: %d\n", rc, 0, 0 );
|
||||
return(rc);
|
||||
}
|
||||
#endif
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include "slap.h"
|
||||
#include "ldapconfig.h"
|
||||
#include "back-ldbm.h"
|
||||
@ -175,7 +174,6 @@ idl_store(
|
||||
|
||||
flags = LDBM_REPLACE;
|
||||
if( li->li_flush_wrt ) flags |= LDBM_SYNC;
|
||||
|
||||
rc = ldbm_cache_store( db, key, data, flags );
|
||||
|
||||
/* Debug( LDAP_DEBUG_TRACE, "<= idl_store %d\n", rc, 0, 0 ); */
|
||||
|
@ -21,6 +21,7 @@ extern int ldbm_back_abandon();
|
||||
extern int ldbm_back_config();
|
||||
extern int ldbm_back_init();
|
||||
extern int ldbm_back_close();
|
||||
extern int ldbm_back_group();
|
||||
#endif
|
||||
|
||||
#ifdef LDAP_PASSWD
|
||||
@ -86,6 +87,9 @@ new_backend(
|
||||
be->be_config = ldbm_back_config;
|
||||
be->be_init = ldbm_back_init;
|
||||
be->be_close = ldbm_back_close;
|
||||
#ifdef ACLGROUP
|
||||
be->be_group = ldbm_back_group;
|
||||
#endif
|
||||
be->be_type = "ldbm";
|
||||
foundit = 1;
|
||||
}
|
||||
@ -105,6 +109,9 @@ new_backend(
|
||||
be->be_config = passwd_back_config;
|
||||
be->be_init = NULL;
|
||||
be->be_close = NULL;
|
||||
#ifdef ACLGROUP
|
||||
be->be_group = NULL;
|
||||
#endif
|
||||
be->be_type = "passwd";
|
||||
foundit = 1;
|
||||
}
|
||||
@ -124,6 +131,9 @@ new_backend(
|
||||
be->be_config = shell_back_config;
|
||||
be->be_init = shell_back_init;
|
||||
be->be_close = NULL;
|
||||
#ifdef ACLGROUP
|
||||
be->be_group = NULL;
|
||||
#endif
|
||||
be->be_type = "shell";
|
||||
foundit = 1;
|
||||
}
|
||||
@ -150,14 +160,6 @@ select_backend( char * dn )
|
||||
for ( i = 0; i < nbackends; i++ ) {
|
||||
for ( j = 0; backends[i].be_suffix != NULL &&
|
||||
backends[i].be_suffix[j] != NULL; j++ ) {
|
||||
/* Add greg@greg.rim.or.jp
|
||||
* It's quick hack for cheep client
|
||||
* Some browser offer a NULL base at ldap_search
|
||||
*/
|
||||
if(dnlen == 0) {
|
||||
Debug( LDAP_DEBUG_TRACE, "select_backend: use default backend\n", 0, 0, 0 );
|
||||
return (&backends[i]);
|
||||
}
|
||||
len = strlen( backends[i].be_suffix[j] );
|
||||
|
||||
if ( len > dnlen ) {
|
||||
@ -239,3 +241,14 @@ be_unbind(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ACLGROUP
|
||||
int
|
||||
be_group(Backend *be, char *bdn, char *edn)
|
||||
{
|
||||
if (be->be_group)
|
||||
return(be->be_group(be, bdn, edn));
|
||||
else
|
||||
return(1);
|
||||
}
|
||||
#endif
|
||||
|
@ -4,22 +4,13 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef sunos5
|
||||
#include "regexpr.h"
|
||||
#else
|
||||
#include "regex.h"
|
||||
#endif
|
||||
#include <regex.h>
|
||||
#include "slap.h"
|
||||
|
||||
extern Attribute *attr_find();
|
||||
extern char *first_word();
|
||||
extern char *next_word();
|
||||
extern char *phonetic();
|
||||
extern char *re_comp();
|
||||
|
||||
#ifndef sunos5
|
||||
extern pthread_mutex_t regex_mutex;
|
||||
#endif
|
||||
|
||||
static int test_filter_list();
|
||||
static int test_substring_filter();
|
||||
@ -323,6 +314,7 @@ test_substring_filter(
|
||||
char pat[BUFSIZ];
|
||||
char buf[BUFSIZ];
|
||||
struct berval *val;
|
||||
regex_t re;
|
||||
|
||||
Debug( LDAP_DEBUG_FILTER, "begin test_substring_filter\n", 0, 0, 0 );
|
||||
|
||||
@ -390,19 +382,16 @@ test_substring_filter(
|
||||
}
|
||||
|
||||
/* compile the regex */
|
||||
#ifdef sunos5
|
||||
if ( (p = compile( pat, NULL, NULL )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "compile failed (%s)\n", p, 0, 0 );
|
||||
Debug( LDAP_DEBUG_FILTER, "test_substring_filter: regcomp pat: %s\n",
|
||||
pat, 0, 0 );
|
||||
if ((rc = regcomp(&re, pat, 0))) {
|
||||
char error[512];
|
||||
|
||||
regerror(rc, &re, error, sizeof(error));
|
||||
Debug( LDAP_DEBUG_ANY, "regcomp failed (%s) %s\n",
|
||||
p, error, 0 );
|
||||
return( -1 );
|
||||
}
|
||||
#else /* sunos5 */
|
||||
pthread_mutex_lock( ®ex_mutex );
|
||||
if ( (p = re_comp( pat )) != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "re_comp failed (%s)\n", p, 0, 0 );
|
||||
pthread_mutex_unlock( ®ex_mutex );
|
||||
return( -1 );
|
||||
}
|
||||
#endif /* sunos5 */
|
||||
|
||||
/* for each value in the attribute see if regex matches */
|
||||
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
|
||||
@ -418,29 +407,18 @@ test_substring_filter(
|
||||
}
|
||||
value_normalize( realval, a->a_syntax );
|
||||
|
||||
#ifdef sunos5
|
||||
rc = step( realval, p );
|
||||
#else /* sunos5 */
|
||||
rc = re_exec( realval );
|
||||
#endif /* sunos5 */
|
||||
rc = !regexec(&re, realval, 0, NULL, 0);
|
||||
|
||||
if ( tmp != NULL ) {
|
||||
free( tmp );
|
||||
}
|
||||
if ( rc == 1 ) {
|
||||
#ifdef sunos5
|
||||
free( p );
|
||||
#else /* sunos5 */
|
||||
pthread_mutex_unlock( ®ex_mutex );
|
||||
#endif /* sunos5 */
|
||||
regfree(&re);
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
#ifdef sunos5
|
||||
free( p );
|
||||
#else /* sunos5 */
|
||||
pthread_mutex_unlock( ®ex_mutex );
|
||||
#endif /* sunos5 */
|
||||
|
||||
regfree(&re);
|
||||
|
||||
Debug( LDAP_DEBUG_FILTER, "end test_substring_filter 1\n", 0, 0, 0 );
|
||||
return( 1 );
|
||||
|
@ -18,9 +18,6 @@ extern pthread_mutex_t entry2str_mutex;
|
||||
extern pthread_mutex_t replog_mutex;
|
||||
extern pthread_mutex_t ops_mutex;
|
||||
extern pthread_mutex_t num_sent_mutex;
|
||||
#ifndef sunos5
|
||||
extern pthread_mutex_t regex_mutex;
|
||||
#endif
|
||||
|
||||
init()
|
||||
{
|
||||
@ -31,7 +28,4 @@ init()
|
||||
pthread_mutex_init( &replog_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( &ops_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( &num_sent_mutex, pthread_mutexattr_default );
|
||||
#ifndef sunos5
|
||||
pthread_mutex_init( ®ex_mutex, pthread_mutexattr_default );
|
||||
#endif
|
||||
}
|
||||
|
@ -56,9 +56,6 @@ pthread_mutex_t num_sent_mutex;
|
||||
*/
|
||||
pthread_mutex_t entry2str_mutex;
|
||||
pthread_mutex_t replog_mutex;
|
||||
#ifndef sunos5
|
||||
pthread_mutex_t regex_mutex;
|
||||
#endif
|
||||
|
||||
static
|
||||
usage( name )
|
||||
|
@ -7,10 +7,13 @@
|
||||
|
||||
int access_allowed( Backend *be, Connection *conn, Operation *op, Entry *e,
|
||||
char *attr, struct berval *val, char *dn, int access );
|
||||
|
||||
struct acl * acl_get_applicable( Backend *be, Operation *op, Entry *e,
|
||||
char *attr );
|
||||
char *attr, char *edn, int nmatches, regmatch_t *matches );
|
||||
int acl_access_allowed( struct acl *a, Backend *be, Connection *conn, Entry *e,
|
||||
struct berval *val, Operation *op, int access );
|
||||
struct berval *val, Operation *op, int access, char *edn,
|
||||
regmatch_t *matches );
|
||||
|
||||
int acl_check_mods( Backend *be, Connection *conn, Operation *op, Entry *e,
|
||||
LDAPMod *mods );
|
||||
|
||||
|
@ -1,908 +0,0 @@
|
||||
#include "portable.h"
|
||||
|
||||
#if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || defined( NEED_BSDREGEX )
|
||||
#include "regex.h"
|
||||
|
||||
/*
|
||||
* regex - Regular expression pattern matching and replacement
|
||||
*
|
||||
* By: Ozan S. Yigit (oz)
|
||||
* Dept. of Computer Science
|
||||
* York University
|
||||
*
|
||||
* These routines are the PUBLIC DOMAIN equivalents of regex
|
||||
* routines as found in 4.nBSD UN*X, with minor extensions.
|
||||
*
|
||||
* These routines are derived from various implementations found
|
||||
* in software tools books, and Conroy's grep. They are NOT derived
|
||||
* from licensed/restricted software.
|
||||
* For more interesting/academic/complicated implementations,
|
||||
* see Henry Spencer's regexp routines, or GNU Emacs pattern
|
||||
* matching module.
|
||||
*
|
||||
* Vendor Modification history:
|
||||
*
|
||||
* Revision 1.2 1996/04/25 16:24:11 mcs
|
||||
* make re_exec() match "" with ".*" and similar patterns
|
||||
* hopefully this change doesn't break anything else!
|
||||
*
|
||||
* Revision 1.1 1995/02/03 15:56:52 tim
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.11 1994/12/14 21:33:45 mcs
|
||||
* use new NEED_BSDREGEX
|
||||
* fix pmatch() prototype
|
||||
*
|
||||
* Revision 1.10 1994/12/12 18:16:39 mcs
|
||||
* use on NetBSD
|
||||
*
|
||||
* Revision 1.9 1994/11/15 19:16:35 mcs
|
||||
* add (CHAR) cast to make VisualC++ happy
|
||||
*
|
||||
* Revision 1.8 1994/11/08 21:14:32 mcs
|
||||
* WIN32 changes
|
||||
*
|
||||
* Revision 1.7 1994/07/23 19:51:24 mcs
|
||||
* use ANSI-style inline function parameters
|
||||
*
|
||||
* Revision 1.6 1993/10/18 01:52:32 tim
|
||||
* include for VMS
|
||||
*
|
||||
* Revision 1.5 1993/09/28 21:37:54 mcs
|
||||
* HP/UX needs the regex we include (not in its libc)
|
||||
*
|
||||
* Revision 1.4 1993/08/27 15:59:52 mcs
|
||||
* use CHAR for deftab
|
||||
*
|
||||
* Revision 1.3 1993/08/27 15:49:47 mcs
|
||||
* added missing 0 to octal constants
|
||||
* use unsigned char for CHAR under DOS
|
||||
*
|
||||
* Revision 1.2 1993/08/27 14:57:48 mcs
|
||||
* add proto. for pmatch
|
||||
*
|
||||
* Revision 1.1 1993/08/18 21:20:02 mcs
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.4 1991/10/17 03:56:42 oz
|
||||
* miscellaneous changes, small cleanups etc.
|
||||
*
|
||||
* Revision 1.3 1989/04/01 14:18:09 oz
|
||||
* Change all references to a dfa: this is actually an nfa.
|
||||
*
|
||||
* Revision 1.2 88/08/28 15:36:04 oz
|
||||
* Use a complement bitmap to represent NCL.
|
||||
* This removes the need to have seperate
|
||||
* code in the pmatch case block - it is
|
||||
* just CCL code now.
|
||||
*
|
||||
* Use the actual CCL code in the CLO
|
||||
* section of pmatch. No need for a recursive
|
||||
* pmatch call.
|
||||
*
|
||||
* Use a bitmap table to set char bits in an
|
||||
* 8-bit chunk.
|
||||
*
|
||||
* Interfaces:
|
||||
* re_comp: compile a regular expression into a NFA.
|
||||
*
|
||||
* char *re_comp(s)
|
||||
* char *s;
|
||||
*
|
||||
* re_exec: execute the NFA to match a pattern.
|
||||
*
|
||||
* int re_exec(s)
|
||||
* char *s;
|
||||
*
|
||||
* re_modw change re_exec's understanding of what a "word"
|
||||
* looks like (for \< and \>) by adding into the
|
||||
* hidden word-syntax table.
|
||||
*
|
||||
* void re_modw(s)
|
||||
* char *s;
|
||||
*
|
||||
* re_subs: substitute the matched portions in a new string.
|
||||
*
|
||||
* int re_subs(src, dst)
|
||||
* char *src;
|
||||
* char *dst;
|
||||
*
|
||||
* re_fail: failure routine for re_exec.
|
||||
*
|
||||
* void re_fail(msg, op)
|
||||
* char *msg;
|
||||
* char op;
|
||||
*
|
||||
* Regular Expressions:
|
||||
*
|
||||
* [1] char matches itself, unless it is a special
|
||||
* character (metachar): . \ [ ] * + ^ $
|
||||
*
|
||||
* [2] . matches any character.
|
||||
*
|
||||
* [3] \ matches the character following it, except
|
||||
* when followed by a left or right round bracket,
|
||||
* a digit 1 to 9 or a left or right angle bracket.
|
||||
* (see [7], [8] and [9])
|
||||
* It is used as an escape character for all
|
||||
* other meta-characters, and itself. When used
|
||||
* in a set ([4]), it is treated as an ordinary
|
||||
* character.
|
||||
*
|
||||
* [4] [set] matches one of the characters in the set.
|
||||
* If the first character in the set is "^",
|
||||
* it matches a character NOT in the set, i.e.
|
||||
* complements the set. A shorthand S-E is
|
||||
* used to specify a set of characters S upto
|
||||
* E, inclusive. The special characters "]" and
|
||||
* "-" have no special meaning if they appear
|
||||
* as the first chars in the set.
|
||||
* examples: match:
|
||||
*
|
||||
* [a-z] any lowercase alpha
|
||||
*
|
||||
* [^]-] any char except ] and -
|
||||
*
|
||||
* [^A-Z] any char except uppercase
|
||||
* alpha
|
||||
*
|
||||
* [a-zA-Z] any alpha
|
||||
*
|
||||
* [5] * any regular expression form [1] to [4], followed by
|
||||
* closure char (*) matches zero or more matches of
|
||||
* that form.
|
||||
*
|
||||
* [6] + same as [5], except it matches one or more.
|
||||
*
|
||||
* [7] a regular expression in the form [1] to [10], enclosed
|
||||
* as \(form\) matches what form matches. The enclosure
|
||||
* creates a set of tags, used for [8] and for
|
||||
* pattern substution. The tagged forms are numbered
|
||||
* starting from 1.
|
||||
*
|
||||
* [8] a \ followed by a digit 1 to 9 matches whatever a
|
||||
* previously tagged regular expression ([7]) matched.
|
||||
*
|
||||
* [9] \< a regular expression starting with a \< construct
|
||||
* \> and/or ending with a \> construct, restricts the
|
||||
* pattern matching to the beginning of a word, and/or
|
||||
* the end of a word. A word is defined to be a character
|
||||
* string beginning and/or ending with the characters
|
||||
* A-Z a-z 0-9 and _. It must also be preceded and/or
|
||||
* followed by any character outside those mentioned.
|
||||
*
|
||||
* [10] a composite regular expression xy where x and y
|
||||
* are in the form [1] to [10] matches the longest
|
||||
* match of x followed by a match for y.
|
||||
*
|
||||
* [11] ^ a regular expression starting with a ^ character
|
||||
* $ and/or ending with a $ character, restricts the
|
||||
* pattern matching to the beginning of the line,
|
||||
* or the end of line. [anchors] Elsewhere in the
|
||||
* pattern, ^ and $ are treated as ordinary characters.
|
||||
*
|
||||
*
|
||||
* Acknowledgements:
|
||||
*
|
||||
* HCR's Hugh Redelmeier has been most helpful in various
|
||||
* stages of development. He convinced me to include BOW
|
||||
* and EOW constructs, originally invented by Rob Pike at
|
||||
* the University of Toronto.
|
||||
*
|
||||
* References:
|
||||
* Software tools Kernighan & Plauger
|
||||
* Software tools in Pascal Kernighan & Plauger
|
||||
* Grep [rsx-11 C dist] David Conroy
|
||||
* ed - text editor Un*x Programmer's Manual
|
||||
* Advanced editing on Un*x B. W. Kernighan
|
||||
* RegExp routines Henry Spencer
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* This implementation uses a bit-set representation for character
|
||||
* classes for speed and compactness. Each character is represented
|
||||
* by one bit in a 128-bit block. Thus, CCL always takes a
|
||||
* constant 16 bytes in the internal nfa, and re_exec does a single
|
||||
* bit comparison to locate the character in the set.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* pattern: foo*.*
|
||||
* compile: CHR f CHR o CLO CHR o END CLO ANY END END
|
||||
* matches: fo foo fooo foobar fobar foxx ...
|
||||
*
|
||||
* pattern: fo[ob]a[rz]
|
||||
* compile: CHR f CHR o CCL bitset CHR a CCL bitset END
|
||||
* matches: fobar fooar fobaz fooaz
|
||||
*
|
||||
* pattern: foo\\+
|
||||
* compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END
|
||||
* matches: foo\ foo\\ foo\\\ ...
|
||||
*
|
||||
* pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo)
|
||||
* compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
|
||||
* matches: foo1foo foo2foo foo3foo
|
||||
*
|
||||
* pattern: \(fo.*\)-\1
|
||||
* compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
|
||||
* matches: foo-foo fo-fo fob-fob foobar-foobar ...
|
||||
*/
|
||||
|
||||
#define MAXNFA 1024
|
||||
#define MAXTAG 10
|
||||
|
||||
#define OKP 1
|
||||
#define NOP 0
|
||||
|
||||
#define CHR 1
|
||||
#define ANY 2
|
||||
#define CCL 3
|
||||
#define BOL 4
|
||||
#define EOL 5
|
||||
#define BOT 6
|
||||
#define EOT 7
|
||||
#define BOW 8
|
||||
#define EOW 9
|
||||
#define REF 10
|
||||
#define CLO 11
|
||||
|
||||
#define END 0
|
||||
|
||||
/*
|
||||
* The following defines are not meant to be changeable.
|
||||
* They are for readability only.
|
||||
*/
|
||||
#define MAXCHR 128
|
||||
#define CHRBIT 8
|
||||
#define BITBLK MAXCHR/CHRBIT
|
||||
#define BLKIND 0170
|
||||
#define BITIND 07
|
||||
|
||||
#define ASCIIB 0177
|
||||
|
||||
#if defined( DOS ) || defined( _WIN32 )
|
||||
typedef unsigned char CHAR;
|
||||
#else /* DOS */
|
||||
typedef /*unsigned*/ char CHAR;
|
||||
#endif /* DOS */
|
||||
|
||||
static int tagstk[MAXTAG]; /* subpat tag stack..*/
|
||||
static CHAR nfa[MAXNFA]; /* automaton.. */
|
||||
static int sta = NOP; /* status of lastpat */
|
||||
|
||||
static CHAR bittab[BITBLK]; /* bit table for CCL */
|
||||
/* pre-set bits... */
|
||||
static CHAR bitarr[] = {1,2,4,8,16,32,64,128};
|
||||
|
||||
static void
|
||||
chset(CHAR c)
|
||||
{
|
||||
bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
|
||||
}
|
||||
|
||||
#define badpat(x) (*nfa = END, x)
|
||||
#define store(x) *mp++ = x
|
||||
|
||||
char *
|
||||
re_comp( char *pat )
|
||||
{
|
||||
register char *p; /* pattern pointer */
|
||||
register CHAR *mp=nfa; /* nfa pointer */
|
||||
register CHAR *lp; /* saved pointer.. */
|
||||
register CHAR *sp=nfa; /* another one.. */
|
||||
|
||||
register int tagi = 0; /* tag stack index */
|
||||
register int tagc = 1; /* actual tag count */
|
||||
|
||||
register int n;
|
||||
register CHAR mask; /* xor mask -CCL/NCL */
|
||||
int c1, c2;
|
||||
|
||||
if (!pat || !*pat)
|
||||
if (sta)
|
||||
return 0;
|
||||
else
|
||||
return badpat("No previous regular expression");
|
||||
sta = NOP;
|
||||
|
||||
for (p = pat; *p; p++) {
|
||||
lp = mp;
|
||||
switch(*p) {
|
||||
|
||||
case '.': /* match any char.. */
|
||||
store(ANY);
|
||||
break;
|
||||
|
||||
case '^': /* match beginning.. */
|
||||
if (p == pat)
|
||||
store(BOL);
|
||||
else {
|
||||
store(CHR);
|
||||
store(*p);
|
||||
}
|
||||
break;
|
||||
|
||||
case '$': /* match endofline.. */
|
||||
if (!*(p+1))
|
||||
store(EOL);
|
||||
else {
|
||||
store(CHR);
|
||||
store(*p);
|
||||
}
|
||||
break;
|
||||
|
||||
case '[': /* match char class..*/
|
||||
store(CCL);
|
||||
|
||||
if (*++p == '^') {
|
||||
mask = 0377;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
mask = 0;
|
||||
|
||||
if (*p == '-') /* real dash */
|
||||
chset(*p++);
|
||||
if (*p == ']') /* real brac */
|
||||
chset(*p++);
|
||||
while (*p && *p != ']') {
|
||||
if (*p == '-' && *(p+1) && *(p+1) != ']') {
|
||||
p++;
|
||||
c1 = *(p-2) + 1;
|
||||
c2 = *p++;
|
||||
while (c1 <= c2)
|
||||
chset((CHAR)c1++);
|
||||
}
|
||||
#ifdef EXTEND
|
||||
else if (*p == '\\' && *(p+1)) {
|
||||
p++;
|
||||
chset(*p++);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
chset(*p++);
|
||||
}
|
||||
if (!*p)
|
||||
return badpat("Missing ]");
|
||||
|
||||
for (n = 0; n < BITBLK; bittab[n++] = (char) 0)
|
||||
store(mask ^ bittab[n]);
|
||||
|
||||
break;
|
||||
|
||||
case '*': /* match 0 or more.. */
|
||||
case '+': /* match 1 or more.. */
|
||||
if (p == pat)
|
||||
return badpat("Empty closure");
|
||||
lp = sp; /* previous opcode */
|
||||
if (*lp == CLO) /* equivalence.. */
|
||||
break;
|
||||
switch(*lp) {
|
||||
|
||||
case BOL:
|
||||
case BOT:
|
||||
case EOT:
|
||||
case BOW:
|
||||
case EOW:
|
||||
case REF:
|
||||
return badpat("Illegal closure");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p == '+')
|
||||
for (sp = mp; lp < sp; lp++)
|
||||
store(*lp);
|
||||
|
||||
store(END);
|
||||
store(END);
|
||||
sp = mp;
|
||||
while (--mp > lp)
|
||||
*mp = mp[-1];
|
||||
store(CLO);
|
||||
mp = sp;
|
||||
break;
|
||||
|
||||
case '\\': /* tags, backrefs .. */
|
||||
switch(*++p) {
|
||||
|
||||
case '(':
|
||||
if (tagc < MAXTAG) {
|
||||
tagstk[++tagi] = tagc;
|
||||
store(BOT);
|
||||
store(tagc++);
|
||||
}
|
||||
else
|
||||
return badpat("Too many \\(\\) pairs");
|
||||
break;
|
||||
case ')':
|
||||
if (*sp == BOT)
|
||||
return badpat("Null pattern inside \\(\\)");
|
||||
if (tagi > 0) {
|
||||
store(EOT);
|
||||
store(tagstk[tagi--]);
|
||||
}
|
||||
else
|
||||
return badpat("Unmatched \\)");
|
||||
break;
|
||||
case '<':
|
||||
store(BOW);
|
||||
break;
|
||||
case '>':
|
||||
if (*sp == BOW)
|
||||
return badpat("Null pattern inside \\<\\>");
|
||||
store(EOW);
|
||||
break;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
n = *p-'0';
|
||||
if (tagi > 0 && tagstk[tagi] == n)
|
||||
return badpat("Cyclical reference");
|
||||
if (tagc > n) {
|
||||
store(REF);
|
||||
store(n);
|
||||
}
|
||||
else
|
||||
return badpat("Undetermined reference");
|
||||
break;
|
||||
#ifdef EXTEND
|
||||
case 'b':
|
||||
store(CHR);
|
||||
store('\b');
|
||||
break;
|
||||
case 'n':
|
||||
store(CHR);
|
||||
store('\n');
|
||||
break;
|
||||
case 'f':
|
||||
store(CHR);
|
||||
store('\f');
|
||||
break;
|
||||
case 'r':
|
||||
store(CHR);
|
||||
store('\r');
|
||||
break;
|
||||
case 't':
|
||||
store(CHR);
|
||||
store('\t');
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
store(CHR);
|
||||
store(*p);
|
||||
}
|
||||
break;
|
||||
|
||||
default : /* an ordinary char */
|
||||
store(CHR);
|
||||
store(*p);
|
||||
break;
|
||||
}
|
||||
sp = lp;
|
||||
}
|
||||
if (tagi > 0)
|
||||
return badpat("Unmatched \\(");
|
||||
store(END);
|
||||
sta = OKP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char *bol;
|
||||
char *bopat[MAXTAG];
|
||||
char *eopat[MAXTAG];
|
||||
#ifdef NEEDPROTOS
|
||||
static char *pmatch( char *lp, CHAR *ap );
|
||||
#else /* NEEDPROTOS */
|
||||
static char *pmatch();
|
||||
#endif /* NEEDPROTOS */
|
||||
|
||||
/*
|
||||
* re_exec:
|
||||
* execute nfa to find a match.
|
||||
*
|
||||
* special cases: (nfa[0])
|
||||
* BOL
|
||||
* Match only once, starting from the
|
||||
* beginning.
|
||||
* CHR
|
||||
* First locate the character without
|
||||
* calling pmatch, and if found, call
|
||||
* pmatch for the remaining string.
|
||||
* END
|
||||
* re_comp failed, poor luser did not
|
||||
* check for it. Fail fast.
|
||||
*
|
||||
* If a match is found, bopat[0] and eopat[0] are set
|
||||
* to the beginning and the end of the matched fragment,
|
||||
* respectively.
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
re_exec( char *lp )
|
||||
{
|
||||
register char c;
|
||||
register char *ep = 0;
|
||||
register CHAR *ap = nfa;
|
||||
|
||||
bol = lp;
|
||||
|
||||
bopat[0] = 0;
|
||||
bopat[1] = 0;
|
||||
bopat[2] = 0;
|
||||
bopat[3] = 0;
|
||||
bopat[4] = 0;
|
||||
bopat[5] = 0;
|
||||
bopat[6] = 0;
|
||||
bopat[7] = 0;
|
||||
bopat[8] = 0;
|
||||
bopat[9] = 0;
|
||||
|
||||
switch(*ap) {
|
||||
|
||||
case BOL: /* anchored: match from BOL only */
|
||||
ep = pmatch(lp,ap);
|
||||
break;
|
||||
case CHR: /* ordinary char: locate it fast */
|
||||
c = *(ap+1);
|
||||
while (*lp && *lp != c)
|
||||
lp++;
|
||||
if (!*lp) /* if EOS, fail, else fall thru. */
|
||||
return 0;
|
||||
default: /* regular matching all the way. */
|
||||
do {
|
||||
if ((ep = pmatch(lp,ap)))
|
||||
break;
|
||||
lp++;
|
||||
} while (*lp);
|
||||
|
||||
break;
|
||||
case END: /* munged automaton. fail always */
|
||||
return 0;
|
||||
}
|
||||
if (!ep)
|
||||
return 0;
|
||||
|
||||
bopat[0] = lp;
|
||||
eopat[0] = ep;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pmatch: internal routine for the hard part
|
||||
*
|
||||
* This code is partly snarfed from an early grep written by
|
||||
* David Conroy. The backref and tag stuff, and various other
|
||||
* innovations are by oz.
|
||||
*
|
||||
* special case optimizations: (nfa[n], nfa[n+1])
|
||||
* CLO ANY
|
||||
* We KNOW .* will match everything upto the
|
||||
* end of line. Thus, directly go to the end of
|
||||
* line, without recursive pmatch calls. As in
|
||||
* the other closure cases, the remaining pattern
|
||||
* must be matched by moving backwards on the
|
||||
* string recursively, to find a match for xy
|
||||
* (x is ".*" and y is the remaining pattern)
|
||||
* where the match satisfies the LONGEST match for
|
||||
* x followed by a match for y.
|
||||
* CLO CHR
|
||||
* We can again scan the string forward for the
|
||||
* single char and at the point of failure, we
|
||||
* execute the remaining nfa recursively, same as
|
||||
* above.
|
||||
*
|
||||
* At the end of a successful match, bopat[n] and eopat[n]
|
||||
* are set to the beginning and end of subpatterns matched
|
||||
* by tagged expressions (n = 1 to 9).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef re_fail
|
||||
extern void re_fail();
|
||||
#endif /* re_fail */
|
||||
|
||||
/*
|
||||
* character classification table for word boundary operators BOW
|
||||
* and EOW. the reason for not using ctype macros is that we can
|
||||
* let the user add into our own table. see re_modw. This table
|
||||
* is not in the bitset form, since we may wish to extend it in the
|
||||
* future for other character classifications.
|
||||
*
|
||||
* TRUE for 0-9 A-Z a-z _
|
||||
*/
|
||||
static char chrtyp[MAXCHR] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
#define inascii(x) (0177&(x))
|
||||
#define iswordc(x) chrtyp[inascii(x)]
|
||||
#define isinset(x,y) ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
|
||||
|
||||
/*
|
||||
* skip values for CLO XXX to skip past the closure
|
||||
*/
|
||||
|
||||
#define ANYSKIP 2 /* [CLO] ANY END ... */
|
||||
#define CHRSKIP 3 /* [CLO] CHR chr END ... */
|
||||
#define CCLSKIP 18 /* [CLO] CCL 16bytes END ... */
|
||||
|
||||
static char *
|
||||
pmatch( char *lp, CHAR *ap)
|
||||
{
|
||||
register int op, c, n;
|
||||
register char *e; /* extra pointer for CLO */
|
||||
register char *bp; /* beginning of subpat.. */
|
||||
register char *ep; /* ending of subpat.. */
|
||||
char *are; /* to save the line ptr. */
|
||||
|
||||
while ((op = *ap++) != END)
|
||||
switch(op) {
|
||||
|
||||
case CHR:
|
||||
if (*lp++ != *ap++)
|
||||
return 0;
|
||||
break;
|
||||
case ANY:
|
||||
if (!*lp++)
|
||||
return 0;
|
||||
break;
|
||||
case CCL:
|
||||
c = *lp++;
|
||||
if (!isinset(ap,c))
|
||||
return 0;
|
||||
ap += BITBLK;
|
||||
break;
|
||||
case BOL:
|
||||
if (lp != bol)
|
||||
return 0;
|
||||
break;
|
||||
case EOL:
|
||||
if (*lp)
|
||||
return 0;
|
||||
break;
|
||||
case BOT:
|
||||
bopat[*ap++] = lp;
|
||||
break;
|
||||
case EOT:
|
||||
eopat[*ap++] = lp;
|
||||
break;
|
||||
case BOW:
|
||||
if (lp!=bol && iswordc(lp[-1]) || !iswordc(*lp))
|
||||
return 0;
|
||||
break;
|
||||
case EOW:
|
||||
if (lp==bol || !iswordc(lp[-1]) || iswordc(*lp))
|
||||
return 0;
|
||||
break;
|
||||
case REF:
|
||||
n = *ap++;
|
||||
bp = bopat[n];
|
||||
ep = eopat[n];
|
||||
while (bp < ep)
|
||||
if (*bp++ != *lp++)
|
||||
return 0;
|
||||
break;
|
||||
case CLO:
|
||||
are = lp;
|
||||
switch(*ap) {
|
||||
|
||||
case ANY:
|
||||
while (*lp)
|
||||
lp++;
|
||||
n = ANYSKIP;
|
||||
break;
|
||||
case CHR:
|
||||
c = *(ap+1);
|
||||
while (*lp && c == *lp)
|
||||
lp++;
|
||||
n = CHRSKIP;
|
||||
break;
|
||||
case CCL:
|
||||
while ((c = *lp) && isinset(ap+1,c))
|
||||
lp++;
|
||||
n = CCLSKIP;
|
||||
break;
|
||||
default:
|
||||
re_fail("closure: bad nfa.", *ap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ap += n;
|
||||
|
||||
while (lp >= are) {
|
||||
if (e = pmatch(lp, ap))
|
||||
return e;
|
||||
--lp;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
re_fail("re_exec: bad nfa.", op);
|
||||
return 0;
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
/*
|
||||
* re_modw:
|
||||
* add new characters into the word table to change re_exec's
|
||||
* understanding of what a word should look like. Note that we
|
||||
* only accept additions into the word definition.
|
||||
*
|
||||
* If the string parameter is 0 or null string, the table is
|
||||
* reset back to the default containing A-Z a-z 0-9 _. [We use
|
||||
* the compact bitset representation for the default table]
|
||||
*/
|
||||
|
||||
static CHAR deftab[16] = {
|
||||
0, 0, 0, 0, 0, 0, 0377, 003, 0376, 0377, 0377, 0207,
|
||||
0376, 0377, 0377, 007
|
||||
};
|
||||
|
||||
void
|
||||
re_modw( char *s )
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (!s || !*s) {
|
||||
for (i = 0; i < MAXCHR; i++)
|
||||
if (!isinset(deftab,i))
|
||||
iswordc(i) = 0;
|
||||
}
|
||||
else
|
||||
while(*s)
|
||||
iswordc(*s++) = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* re_subs:
|
||||
* substitute the matched portions of the src in dst.
|
||||
*
|
||||
* & substitute the entire matched pattern.
|
||||
*
|
||||
* \digit substitute a subpattern, with the given tag number.
|
||||
* Tags are numbered from 1 to 9. If the particular
|
||||
* tagged subpattern does not exist, null is substituted.
|
||||
*/
|
||||
int
|
||||
re_subs( char *src, char *dst)
|
||||
{
|
||||
register char c;
|
||||
register int pin;
|
||||
register char *bp;
|
||||
register char *ep;
|
||||
|
||||
if (!*src || !bopat[0])
|
||||
return 0;
|
||||
|
||||
while (c = *src++) {
|
||||
switch(c) {
|
||||
|
||||
case '&':
|
||||
pin = 0;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
c = *src++;
|
||||
if (c >= '0' && c <= '9') {
|
||||
pin = c - '0';
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
*dst++ = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((bp = bopat[pin]) && (ep = eopat[pin])) {
|
||||
while (*bp && bp < ep)
|
||||
*dst++ = *bp++;
|
||||
if (bp < ep)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*dst = (char) 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* symbolic - produce a symbolic dump of the nfa
|
||||
*/
|
||||
symbolic( char *s )
|
||||
{
|
||||
printf("pattern: %s\n", s);
|
||||
printf("nfacode:\n");
|
||||
nfadump(nfa);
|
||||
}
|
||||
|
||||
static
|
||||
nfadump( CHAR *ap)
|
||||
{
|
||||
register int n;
|
||||
|
||||
while (*ap != END)
|
||||
switch(*ap++) {
|
||||
case CLO:
|
||||
printf("CLOSURE");
|
||||
nfadump(ap);
|
||||
switch(*ap) {
|
||||
case CHR:
|
||||
n = CHRSKIP;
|
||||
break;
|
||||
case ANY:
|
||||
n = ANYSKIP;
|
||||
break;
|
||||
case CCL:
|
||||
n = CCLSKIP;
|
||||
break;
|
||||
}
|
||||
ap += n;
|
||||
break;
|
||||
case CHR:
|
||||
printf("\tCHR %c\n",*ap++);
|
||||
break;
|
||||
case ANY:
|
||||
printf("\tANY .\n");
|
||||
break;
|
||||
case BOL:
|
||||
printf("\tBOL -\n");
|
||||
break;
|
||||
case EOL:
|
||||
printf("\tEOL -\n");
|
||||
break;
|
||||
case BOT:
|
||||
printf("BOT: %d\n",*ap++);
|
||||
break;
|
||||
case EOT:
|
||||
printf("EOT: %d\n",*ap++);
|
||||
break;
|
||||
case BOW:
|
||||
printf("BOW\n");
|
||||
break;
|
||||
case EOW:
|
||||
printf("EOW\n");
|
||||
break;
|
||||
case REF:
|
||||
printf("REF: %d\n",*ap++);
|
||||
break;
|
||||
case CCL:
|
||||
printf("\tCCL [");
|
||||
for (n = 0; n < MAXCHR; n++)
|
||||
if (isinset(ap,(CHAR)n)) {
|
||||
if (n < ' ')
|
||||
printf("^%c", n ^ 0x040);
|
||||
else
|
||||
printf("%c", n);
|
||||
}
|
||||
printf("]\n");
|
||||
ap += BITBLK;
|
||||
break;
|
||||
default:
|
||||
printf("bad nfa. opcode %o\n", ap[-1]);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* MACOS or DOS or NEED_BSDREGEX */
|
@ -121,11 +121,13 @@ send_ldap_result2(
|
||||
pthread_mutex_lock( &active_threads_mutex );
|
||||
active_threads--;
|
||||
conn->c_writewaiter = 1;
|
||||
|
||||
#ifdef linux
|
||||
pthread_kill( listener_tid, SIGSTKFLT );
|
||||
#else /* !linux */
|
||||
pthread_kill( listener_tid, SIGUSR1 );
|
||||
#endif /* !linux */
|
||||
|
||||
pthread_cond_wait( &conn->c_wcv, &active_threads_mutex );
|
||||
pthread_mutex_unlock( &active_threads_mutex );
|
||||
|
||||
@ -196,6 +198,7 @@ send_search_entry(
|
||||
Attribute *a;
|
||||
int i, rc, bytes, sd;
|
||||
struct acl *acl;
|
||||
char *edn;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
|
||||
|
||||
@ -206,15 +209,19 @@ send_search_entry(
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
edn = dn_normalize_case( strdup( e->e_dn ) );
|
||||
|
||||
#ifdef COMPAT30
|
||||
if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
|
||||
== NULLBER ) {
|
||||
== NULLBER )
|
||||
#else
|
||||
if ( (ber = der_alloc()) == NULLBER ) {
|
||||
if ( (ber = der_alloc()) == NULLBER )
|
||||
#endif
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
|
||||
"ber_alloc" );
|
||||
"ber_alloc" );
|
||||
free(edn);
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
@ -224,26 +231,44 @@ send_search_entry(
|
||||
LDAP_RES_SEARCH_ENTRY, e->e_dn );
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
rc = ber_printf( ber, "{it{s{", op->o_msgid,
|
||||
LDAP_RES_SEARCH_ENTRY, e->e_dn );
|
||||
LDAP_RES_SEARCH_ENTRY, e->e_dn );
|
||||
}
|
||||
|
||||
if ( rc == -1 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
|
||||
ber_free( ber, 1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
|
||||
"ber_printf dn" );
|
||||
free(edn);
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
|
||||
regmatch_t matches[MAXREMATCHES];
|
||||
|
||||
if ( attrs != NULL && ! charray_inlist( attrs, a->a_type ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
acl = acl_get_applicable( be, op, e, a->a_type );
|
||||
/* the lastmod attributes are ignored by ACL checking */
|
||||
if ( strcasecmp( a->a_type, "modifiersname" ) == 0 ||
|
||||
strcasecmp( a->a_type, "modifytimestamp" ) == 0 ||
|
||||
strcasecmp( a->a_type, "creatorsname" ) == 0 ||
|
||||
strcasecmp( a->a_type, "createtimestamp" ) == 0 )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ACL, "LASTMOD attribute: %s access DEFAULT\n",
|
||||
a->a_type, 0, 0 );
|
||||
acl = NULL;
|
||||
} else {
|
||||
acl = acl_get_applicable( be, op, e, a->a_type, edn,
|
||||
MAXREMATCHES, matches );
|
||||
}
|
||||
|
||||
if ( ! acl_access_allowed( acl, be, conn, e, NULL, op,
|
||||
ACL_READ ) ) {
|
||||
if ( ! acl_access_allowed( acl, be, conn, e, NULL, op, ACL_READ,
|
||||
edn, matches ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -252,14 +277,15 @@ send_search_entry(
|
||||
ber_free( ber, 1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, "ber_printf type" );
|
||||
free(edn);
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( ! attrsonly ) {
|
||||
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
|
||||
if ( a->a_syntax & SYNTAX_DN &&
|
||||
! acl_access_allowed( acl, be, conn, e,
|
||||
a->a_vals[i], op, ACL_READ ) )
|
||||
if ( a->a_syntax & SYNTAX_DN &&
|
||||
! acl_access_allowed( acl, be, conn, e, a->a_vals[i], op,
|
||||
ACL_READ, edn, matches) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -274,6 +300,7 @@ send_search_entry(
|
||||
send_ldap_result( conn, op,
|
||||
LDAP_OPERATIONS_ERROR, NULL,
|
||||
"ber_printf value" );
|
||||
free(edn);
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
@ -284,10 +311,13 @@ send_search_entry(
|
||||
ber_free( ber, 1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, "ber_printf type end" );
|
||||
free(edn);
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
free(edn);
|
||||
|
||||
#ifdef COMPAT30
|
||||
if ( conn->c_version == 30 ) {
|
||||
rc = ber_printf( ber, "}}}}" );
|
||||
|
@ -6,6 +6,9 @@
|
||||
#define LDAP_SYSLOG
|
||||
|
||||
#include <syslog.h>
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include "avl.h"
|
||||
#include "lber.h"
|
||||
#include "ldap.h"
|
||||
@ -19,6 +22,8 @@
|
||||
#define OFF (-1)
|
||||
#define UNDEFINED 0
|
||||
|
||||
#define MAXREMATCHES 10
|
||||
|
||||
/*
|
||||
* represents an attribute value assertion (i.e., attr=value)
|
||||
*/
|
||||
@ -122,6 +127,11 @@ struct access {
|
||||
char *a_domainpat;
|
||||
char *a_dnattr;
|
||||
long a_access;
|
||||
|
||||
#ifdef ACLGROUP
|
||||
char *a_group;
|
||||
#endif
|
||||
|
||||
#define ACL_NONE 0x01
|
||||
#define ACL_COMPARE 0x02
|
||||
#define ACL_SEARCH 0x04
|
||||
@ -135,6 +145,7 @@ struct access {
|
||||
struct acl {
|
||||
/* "to" part: the entries this acl applies to */
|
||||
Filter *acl_filter;
|
||||
regex_t acl_dnre;
|
||||
char *acl_dnpat;
|
||||
char **acl_attrs;
|
||||
|
||||
@ -188,6 +199,10 @@ typedef struct backend {
|
||||
IFP be_config; /* backend config routine */
|
||||
IFP be_init; /* backend init routine */
|
||||
IFP be_close; /* backend close routine */
|
||||
|
||||
#ifdef ACLGROUP
|
||||
IFP be_group; /* backend group member test */
|
||||
#endif
|
||||
} Backend;
|
||||
|
||||
/*
|
||||
|
@ -24,7 +24,7 @@ OBJS2 = ../config.o ../ch_malloc.o ../backend.o ../charray.o \
|
||||
../aclparse.o ../schema.o ../result.o ../filterentry.o \
|
||||
../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
|
||||
../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
|
||||
../schemaparse.o ../regex.o ../strdup.o
|
||||
../schemaparse.o ../strdup.o
|
||||
|
||||
INCLUDES= -I. -I$(HDIR) $(EXINCLUDES)
|
||||
DEFINES = $(DEFS) $(LDAP_CRYPT) $(SERVERDEFS) $(THREADS)
|
||||
|
@ -21,8 +21,6 @@ multilinedescription: Outstanding
|
||||
title: Mad Cow Researcher, UM Alumni Association
|
||||
pager: +1 313 555 3923
|
||||
mail: jaj@mail.alumni.umich.edu
|
||||
modifytimestamp: 960404171231Z
|
||||
modifiersname: cn=Manager,o=University of Michigan,c=US
|
||||
facsimiletelephonenumber: +1 313 555 4332
|
||||
telephonenumber: +1 313 555 0895
|
||||
dn: cn=All Staff,ou=Groups,o=University of Michigan,c=US
|
||||
@ -180,7 +178,6 @@ member: cn=John Doe, ou=Information Technology Division, ou=People, o=Universi
|
||||
member: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of
|
||||
Michigan, c=US
|
||||
labeledurl: http://www.itd.umich.edu ITD Home Page
|
||||
University of Michigan,c=US
|
||||
telephonenumber: +1 810 555 1212
|
||||
|
||||
dn: cn=James A Jones 2, ou=Information Technology Division, ou=People, o=Unive
|
||||
|
@ -1,5 +1,2 @@
|
||||
#!/bin/sh
|
||||
grep -v "modifiersname" | \
|
||||
grep -v "modifytimestamp" | \
|
||||
grep -v "creatorsname" | \
|
||||
grep -v "createtimestamp"
|
||||
egrep -iv '^modifiersname:|^modifytimestamp:|^creatorsname:|^createtimestamp'
|
||||
|
@ -50,6 +50,7 @@ echo "Filtering original ldif used to create database..."
|
||||
. scripts/acfilter.sh < $LDIF > $LDIFFLT
|
||||
echo "Comparing filter output..."
|
||||
cmp $SEARCHFLT $LDIFFLT
|
||||
|
||||
if [ $? != 0 ]; then
|
||||
echo "comparison failed - database was not created correctly"
|
||||
exit 1
|
||||
|
@ -96,8 +96,7 @@ EOMODS4
|
||||
|
||||
echo "Using ldapsearch to retrieve all the entries..."
|
||||
$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
|
||||
'objectClass=*' | egrep -iv '^modifytimestamp|^modifiersname' \
|
||||
>> $SEARCHOUT 2>&1
|
||||
'objectClass=*' | . scripts/acfilter.sh >> $SEARCHOUT 2>&1
|
||||
RC=$?
|
||||
kill -HUP $PID
|
||||
if [ $RC != 0 ]; then
|
||||
|
Loading…
Reference in New Issue
Block a user