From 4d9941b0f2e5dfbc8399449d5d27fabe5b6a42b7 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Fri, 21 Aug 1998 05:51:28 +0000 Subject: [PATCH] Working ACLs! --- build/platforms/freebsd-gcc/Make-platform | 32 +- include/{regex.h => compat_regex.h} | 0 libraries/libldap/Make-template | 79 +- libraries/libldap/getfilter.c | 57 +- libraries/libldap/regex.c | 906 --------------------- servers/slapd/Make-template | 140 +--- servers/slapd/acl.c | 388 ++++++--- servers/slapd/aclparse.c | 133 +++- servers/slapd/back-ldbm/Make-template | 86 +- servers/slapd/back-ldbm/group.c | 90 +++ servers/slapd/back-ldbm/idl.c | 15 +- servers/slapd/backend.c | 21 + servers/slapd/filterentry.c | 53 +- servers/slapd/init.c | 6 - servers/slapd/main.c | 37 +- servers/slapd/proto-slap.h | 7 +- servers/slapd/regex.c | 909 ---------------------- servers/slapd/result.c | 54 +- servers/slapd/slap.h | 16 + servers/slapd/tools/Make-template | 112 +-- tests/data/acl.out.master | 3 - tests/scripts/acfilter.sh | 2 + tests/scripts/test002-populate | 13 +- tests/scripts/test006-acls | 7 +- 24 files changed, 755 insertions(+), 2411 deletions(-) rename include/{regex.h => compat_regex.h} (100%) delete mode 100644 libraries/libldap/regex.c create mode 100644 servers/slapd/back-ldbm/group.c delete mode 100644 servers/slapd/regex.c create mode 100755 tests/scripts/acfilter.sh diff --git a/build/platforms/freebsd-gcc/Make-platform b/build/platforms/freebsd-gcc/Make-platform index 895b32f2af..f5750b49ce 100644 --- a/build/platforms/freebsd-gcc/Make-platform +++ b/build/platforms/freebsd-gcc/Make-platform @@ -6,11 +6,41 @@ # # add any platform-specific overrides below here # +EXTRACFLAGS=-O -g +LDBMBACKEND=-DLDBM_USE_DBBTREE +LDBMINCLUDE=-I/usr/include + +EDITOR=/usr/bin/vi +FINGER=/usr/bin/finger +SENDMAIL=/usr/sbin/sendmail + +LDAP_RUNDIR=/var/run + +MANCOMPRESS=gzip +MANCOMPRESSSUFFIX=.gz + + +# +# LDAP has a problem with the idea of implicit vs. explicit yields +# in call conversion threading packages, like the MIT pthreads +# package. Rather than resolve this globally, I have marked the +# threading as "preeemptive", even though it is technically not. +# +# This means that the implicit-yield threading is topologically +# equivalent to preemptive threading. +# +THREADS= -DPOSIX_THREADS -D_THREAD_SAFE -DPTHREAD_PREEMPTIVE + +# use special gcc flag to include libc_r.a +THREADSLIB= -pthread +#THREADSLIB= -lc_r + +# crypt(3) is in a separate library +LDAP_CRYPT_LIB= -lcrypt # # ------------------------------------------------------------------------- # you will probably not need to edit anything below this point # ------------------------------------------------------------------------- CC = gcc - PLATFORMCFLAGS= -Dfreebsd diff --git a/include/regex.h b/include/compat_regex.h similarity index 100% rename from include/regex.h rename to include/compat_regex.h diff --git a/libraries/libldap/Make-template b/libraries/libldap/Make-template index 9ca5d7f234..a100e22825 100644 --- a/libraries/libldap/Make-template +++ b/libraries/libldap/Make-template @@ -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 @@ -31,8 +31,7 @@ OBJS = bind.o open.o result.o error.o compare.o search.o \ HDIR = ../../include INCLUDES= -I$(HDIR) $(KRBINCLUDEFLAG) -DEFINES = $(DEFS) -DFILTERFILE="\"$(RUNTIMEETCDIR)/ldapfilter.conf\"" \ - -DTEMPLATEFILE="\"$(RUNTIMEETCDIR)/ldaptemplates.conf\"" +DEFINES = $(DEFS) CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS) LIBS = -L. -L../liblber -lldap -llber $(KRBLIBFLAG) $(KRBLIBS) $(ALIBS) @@ -62,20 +61,20 @@ version.c: $(OBJS) < Version.c > $@) install: libldap.a ldapfilter.conf ldapfriendly ldaptemplates.conf ldapsearchprefs.conf FORCE - -$(MKDIR) -p $(LIBDIR) - $(INSTALL) $(INSTALLFLAGS) -m 644 libldap.a $(LIBDIR) + -$(MKDIR) -p $(LDAP_LIBDIR) $(LDAP_ETCDIR) + $(INSTALL) $(INSTALLFLAGS) -m 644 libldap.a $(LDAP_LIBDIR) @if [ ! -z "$(RANLIB)" ]; then \ - (cd /tmp; $(RANLIB) $(LIBDIR)/libldap.a) \ + (cd /tmp; $(RANLIB) $(LDAP_LIBDIR)/libldap.a) \ fi - -$(MKDIR) -p $(ETCDIR) - -$(MV) $(ETCDIR)/ldapfriendly $(ETCDIR)/ldapfriendly- - $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfriendly $(ETCDIR) - -$(MV) $(ETCDIR)/ldapfilter.conf $(ETCDIR)/ldapfilter.conf- - $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfilter.conf $(ETCDIR) - -$(MV) $(ETCDIR)/ldaptemplates.conf $(ETCDIR)/ldaptemplates.conf- - $(INSTALL) $(INSTALLFLAGS) -m 644 ldaptemplates.conf $(ETCDIR) - -$(MV) $(ETCDIR)/ldapsearchprefs.conf $(ETCDIR)/ldapsearchprefs.conf- - $(INSTALL) $(INSTALLFLAGS) -m 644 ldapsearchprefs.conf $(ETCDIR) + -$(MKDIR) -p $(LDAP_ETCDIR) + -$(MV) $(LDAP_ETCDIR)/ldapfriendly $(LDAP_ETCDIR)/ldapfriendly- + $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfriendly $(LDAP_ETCDIR) + -$(MV) $(LDAP_ETCDIR)/ldapfilter.conf $(LDAP_ETCDIR)/ldapfilter.conf- + $(INSTALL) $(INSTALLFLAGS) -m 644 ldapfilter.conf $(LDAP_ETCDIR) + -$(MV) $(LDAP_ETCDIR)/ldaptemplates.conf $(LDAP_ETCDIR)/ldaptemplates.conf- + $(INSTALL) $(INSTALLFLAGS) -m 644 ldaptemplates.conf $(LDAP_ETCDIR) + -$(MV) $(LDAP_ETCDIR)/ldapsearchprefs.conf $(LDAP_ETCDIR)/ldapsearchprefs.conf- + $(INSTALL) $(INSTALLFLAGS) -m 644 ldapsearchprefs.conf $(LDAP_ETCDIR) lint: FORCE $(LINT) $(INCLUDES) $(DEFINES) $(SRCS) @@ -93,51 +92,3 @@ links: @$(LN) .src/*.[ch] .src/ldapfriendly .src/ldapfilter.conf \ .src/ldaptemplates.conf .src/ldapsearchprefs.conf . -# DO NOT DELETE THIS LINE -- mkdep uses it. -# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. - -bind.o: bind.c ../../include/lber.h ../../include/ldap.h -open.o: open.c ../../include/lber.h ../../include/ldap.h ldap-int.h -result.o: result.c ../../include/portable.h ../../include/lber.h -result.o: ../../include/ldap.h ldap-int.h -error.o: error.c ../../include/lber.h ../../include/ldap.h -compare.o: compare.c ../../include/lber.h ../../include/ldap.h ldap-int.h -search.o: search.c ../../include/lber.h ../../include/ldap.h ldap-int.h -modify.o: modify.c ../../include/lber.h ../../include/ldap.h ldap-int.h -add.o: add.c ../../include/lber.h ../../include/ldap.h ldap-int.h -modrdn.o: modrdn.c ../../include/lber.h ../../include/ldap.h ldap-int.h -delete.o: delete.c ../../include/lber.h ../../include/ldap.h ldap-int.h -abandon.o: abandon.c ../../include/lber.h ../../include/ldap.h ldap-int.h -ufn.o: ufn.c ../../include/lber.h ../../include/ldap.h -cache.o: cache.c ../../include/lber.h ../../include/ldap.h ldap-int.h -getfilter.o: getfilter.c ../../include/lber.h ../../include/ldap.h -getfilter.o: ../../include/regex.h -regex.o: regex.c ../../include/portable.h -sbind.o: sbind.c ../../include/lber.h ../../include/ldap.h ldap-int.h -kbind.o: kbind.c ../../include/lber.h ../../include/ldap.h ldap-int.h -unbind.o: unbind.c ../../include/lber.h ../../include/ldap.h ldap-int.h -friendly.o: friendly.c ../../include/lber.h ../../include/ldap.h -cldap.o: cldap.c ../../include/lber.h ../../include/ldap.h ldap-int.h -free.o: free.c ../../include/lber.h ../../include/ldap.h -disptmpl.o: disptmpl.c ../../include/lber.h ../../include/ldap.h -disptmpl.o: ../../include/disptmpl.h -srchpref.o: srchpref.c ../../include/lber.h ../../include/ldap.h -srchpref.o: ../../include/srchpref.h -dsparse.o: dsparse.c ../../include/lber.h ../../include/ldap.h -tmplout.o: tmplout.c ../../include/lber.h ../../include/ldap.h -tmplout.o: ../../include/disptmpl.h -sort.o: sort.c ../../include/lber.h ../../include/ldap.h -getdn.o: getdn.c ../../include/lber.h ../../include/ldap.h -getentry.o: getentry.c ../../include/lber.h ../../include/ldap.h -getattr.o: getattr.c ../../include/lber.h ../../include/ldap.h ldap-int.h -getvalues.o: getvalues.c ../../include/lber.h ../../include/ldap.h -addentry.o: addentry.c ../../include/lber.h ../../include/ldap.h -request.o: request.c ../../include/portable.h ../../include/lber.h -request.o: ../../include/ldap.h ldap-int.h -getdxbyname.o: getdxbyname.c -os-ip.o: os-ip.c ../../include/portable.h ../../include/lber.h -os-ip.o: ../../include/ldap.h -url.o: url.c ../../include/lber.h ../../include/ldap.h ldap-int.h -charset.o: charset.c - -# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/libraries/libldap/getfilter.c b/libraries/libldap/getfilter.c index e9ebc6aa29..a2f9267968 100644 --- a/libraries/libldap/getfilter.c +++ b/libraries/libldap/getfilter.c @@ -10,13 +10,13 @@ static char copyright[] = "@(#) Copyright (c) 1993 Regents of the University of #endif #include +#include #include #include -#if defined(NeXT) +#include #include -#endif + #ifdef MACOS -#include #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 #include -#include #include #ifndef VMS #include @@ -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 ) { diff --git a/libraries/libldap/regex.c b/libraries/libldap/regex.c deleted file mode 100644 index 4f309c5fb0..0000000000 --- a/libraries/libldap/regex.c +++ /dev/null @@ -1,906 +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. - * - * Modification history: - * - * $Log: regex.c,v $ - * 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 */ diff --git a/servers/slapd/Make-template b/servers/slapd/Make-template index d3a5f49884..25a827a904 100644 --- a/servers/slapd/Make-template +++ b/servers/slapd/Make-template @@ -21,23 +21,24 @@ 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) $(SERVERDEFS) +DEFINES = $(DEFS) $(LDAP_CRYPT) $(LDAP_TCP_WRAPPERS) $(SERVERDEFS) CFLAGS = $(INCLUDES) $(THREADSINCLUDE) $(DEFINES) $(ACFLAGS) $(THREADS) LDFLAGS = -L$(LDIR) $(KRBLIBFLAG) -LIBS = $(KRBLIBS) -llber -lldbm -lavl -llthread -lldif $(THREADSLIB) \ - $(LDBMLIB) $(ALIBS) +LIBS = $(KRBLIBS) -llber -lldbm -lavl -llthread -lldif \ + $(REGEXLIB) $(THREADSLIB) \ + $(LDBMLIB) $(LDAP_CRYPT_LIB) $(LDAP_TCP_WRAPPERS_LIB) $(ALIBS) all: FORCE @if [ -z "$(MAKESLAPD)" ]; then \ @@ -100,26 +101,27 @@ version.c: libbackends.a $(OBJS) $(LDIR)/liblber/liblber.a \ -e "s|%VERSION%|$${v}|" \ < Version.c > $@) -install: all $(ETCDIR) $(ETCDIR)/slapd $(ETCDIR)/slapd.conf \ - $(ETCDIR)/slapd.at.conf $(ETCDIR)/slapd.oc.conf \ +install: all $(LDAP_LIBEXECDIR) $(LDAP_LIBEXECDIR)/slapd \ + $(LDAP_ETCDIR) $(LDAP_ETCDIR)/slapd.conf \ + $(LDAP_ETCDIR)/slapd.at.conf $(LDAP_ETCDIR)/slapd.oc.conf \ install-tools -$(ETCDIR)/slapd: slapd - $(INSTALL) $(INSTALLFLAGS) -m 755 slapd $(ETCDIR) +$(LDAP_LIBEXECDIR)/slapd: slapd + $(INSTALL) $(INSTALLFLAGS) -m 755 slapd $(LDAP_LIBEXECDIR) -$(ETCDIR)/slapd.conf: slapd.conf - $(SED) -e 's;%ETCDIR%;$(RUNTIMEETCDIR);' slapd.conf > /tmp/slapd.$$ - -$(MV) $(ETCDIR)/slapd.conf $(ETCDIR)/slapd.conf- - $(INSTALL) $(INSTALLFLAGS) -m 644 /tmp/slapd.$$ $(ETCDIR)/slapd.conf +$(LDAP_ETCDIR)/slapd.conf: slapd.conf + $(SED) -e 's;%ETCDIR%;$(LDAP_ETCDIR);' slapd.conf > /tmp/slapd.$$ + -$(MV) $(LDAP_ETCDIR)/slapd.conf $(LDAP_ETCDIR)/slapd.conf- + $(INSTALL) $(INSTALLFLAGS) -m 644 /tmp/slapd.$$ $(LDAP_ETCDIR)/slapd.conf $(RM) -f /tmp/slapd.$$ -$(ETCDIR)/slapd.at.conf: slapd.at.conf - -$(MV) $(ETCDIR)/slapd.at.conf $(ETCDIR)/slapd.at.conf- - $(INSTALL) $(INSTALLFLAGS) -m 644 slapd.at.conf $(ETCDIR) +$(LDAP_ETCDIR)/slapd.at.conf: slapd.at.conf + -$(MV) $(LDAP_ETCDIR)/slapd.at.conf $(LDAP_ETCDIR)/slapd.at.conf- + $(INSTALL) $(INSTALLFLAGS) -m 644 slapd.at.conf $(LDAP_ETCDIR) -$(ETCDIR)/slapd.oc.conf: slapd.oc.conf - -$(MV) $(ETCDIR)/slapd.oc.conf $(ETCDIR)/slapd.oc.conf- - $(INSTALL) $(INSTALLFLAGS) -m 644 slapd.oc.conf $(ETCDIR) +$(LDAP_ETCDIR)/slapd.oc.conf: slapd.oc.conf + -$(MV) $(LDAP_ETCDIR)/slapd.oc.conf $(LDAP_ETCDIR)/slapd.oc.conf- + $(INSTALL) $(INSTALLFLAGS) -m 644 slapd.oc.conf $(LDAP_ETCDIR) install-tools: FORCE (cd tools; $(MAKE) $(MFLAGS) install) @@ -164,103 +166,3 @@ links: fi; \ done; - -# DO NOT DELETE THIS LINE -- mkdep uses it. -# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. - -main.o: main.c ../../include/portable.h slap.h ../../include/avl.h -main.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -main.o: ../../include/ldif.h ../../include/ldapconfig.h -daemon.o: daemon.c slap.h ../../include/avl.h ../../include/lber.h -daemon.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -daemon.o: ../../include/portable.h ../../include/ldapconfig.h -connection.o: connection.c ../../include/portable.h slap.h ../../include/avl.h -connection.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -connection.o: ../../include/ldif.h -search.o: search.c slap.h ../../include/avl.h ../../include/lber.h -search.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -search.o: ../../include/ldapconfig.h -filter.o: filter.c slap.h ../../include/avl.h ../../include/lber.h -filter.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -add.o: add.c slap.h ../../include/avl.h ../../include/lber.h -add.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -charray.o: charray.c slap.h ../../include/avl.h ../../include/lber.h -charray.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -attr.o: attr.c ../../include/portable.h slap.h ../../include/avl.h -attr.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -attr.o: ../../include/ldif.h -entry.o: entry.c slap.h ../../include/avl.h ../../include/lber.h -entry.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -config.o: config.c slap.h ../../include/avl.h ../../include/lber.h -config.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -config.o: ../../include/ldapconfig.h -backend.o: backend.c slap.h ../../include/avl.h ../../include/lber.h -backend.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -result.o: result.c ../../include/portable.h slap.h ../../include/avl.h -result.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -result.o: ../../include/ldif.h -operation.o: operation.c slap.h ../../include/avl.h ../../include/lber.h -operation.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -dn.o: dn.c ../../include/portable.h slap.h ../../include/avl.h -dn.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -dn.o: ../../include/ldif.h -compare.o: compare.c slap.h ../../include/avl.h ../../include/lber.h -compare.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -modify.o: modify.c slap.h ../../include/avl.h ../../include/lber.h -modify.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -delete.o: delete.c slap.h ../../include/avl.h ../../include/lber.h -delete.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -modrdn.o: modrdn.c slap.h ../../include/avl.h ../../include/lber.h -modrdn.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -ch_malloc.o: ch_malloc.c slap.h ../../include/avl.h ../../include/lber.h -ch_malloc.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -value.o: value.c ../../include/portable.h slap.h ../../include/avl.h -value.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -value.o: ../../include/ldif.h -ava.o: ava.c slap.h ../../include/avl.h ../../include/lber.h -ava.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -bind.o: bind.c slap.h ../../include/avl.h ../../include/lber.h -bind.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -unbind.o: unbind.c slap.h ../../include/avl.h ../../include/lber.h -unbind.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -abandon.o: abandon.c slap.h ../../include/avl.h ../../include/lber.h -abandon.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -filterentry.o: filterentry.c ../../include/regex.h slap.h ../../include/avl.h -filterentry.o: ../../include/lber.h ../../include/ldap.h -filterentry.o: ../../include/lthread.h ../../include/ldif.h -phonetic.o: phonetic.c ../../include/portable.h slap.h ../../include/avl.h -phonetic.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -phonetic.o: ../../include/ldif.h -regex.o: regex.c ../../include/portable.h -acl.o: acl.c ../../include/regex.h slap.h ../../include/avl.h -acl.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -acl.o: ../../include/ldif.h -str2filter.o: str2filter.c slap.h ../../include/avl.h ../../include/lber.h -str2filter.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -aclparse.o: aclparse.c ../../include/regex.h slap.h ../../include/avl.h -aclparse.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -aclparse.o: ../../include/ldif.h ../../include/portable.h -init.o: init.c ../../include/portable.h slap.h ../../include/avl.h -init.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -init.o: ../../include/ldif.h -detach.o: detach.c ../../include/portable.h -strdup.o: strdup.c -tempnam.o: tempnam.c -repl.o: repl.c slap.h ../../include/avl.h ../../include/lber.h -repl.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -lock.o: lock.c ../../include/portable.h slap.h ../../include/avl.h -lock.o: ../../include/lber.h ../../include/ldap.h ../../include/lthread.h -lock.o: ../../include/ldif.h -schema.o: schema.c slap.h ../../include/avl.h ../../include/lber.h -schema.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -schemaparse.o: schemaparse.c slap.h ../../include/avl.h ../../include/lber.h -schemaparse.o: ../../include/ldap.h ../../include/lthread.h -schemaparse.o: ../../include/ldif.h -monitor.o: monitor.c slap.h ../../include/avl.h ../../include/lber.h -monitor.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -monitor.o: ../../include/ldapconfig.h -configinfo.o: configinfo.c slap.h ../../include/avl.h ../../include/lber.h -configinfo.o: ../../include/ldap.h ../../include/lthread.h ../../include/ldif.h -configinfo.o: ../../include/ldapconfig.h - -# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 6c3b22ee85..6917f5e171 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -6,15 +6,11 @@ #include #include #include -#ifdef sunos5 -#include "regexpr.h" -#else -#include "regex.h" -#endif +#include + #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 ); } + + matches[0].rm_so = matches[0].rm_eo = -1; } - Debug( LDAP_DEBUG_ACL, "<= acl_get: no match\n", 0, 0, 0 ); + 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 ); + if ( odn ) free( odn ); + return( (b->a_access & ~ACL_SELF) >= access ); } - free( edn ); } else { - if ( regex_matches( b->a_dnpat, odn ) ) { - if ( odn ) free( odn ); + 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; - - if ( (e = compile( pat, NULL, NULL )) == NULL ) { - Debug( LDAP_DEBUG_ANY, - "compile( \"%s\", \"%s\") failed\n", pat, str, 0 ); - return( 0 ); + int size; + char *sp; + char *dp; + int flag; + + 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 */ diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 10fa6a0721..3d853222c6 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -7,12 +7,13 @@ #include #include #include -#include "regex.h" +#include +#include + #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 got \"%s\"\n", + "%s: line %d: expecting 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 */ diff --git a/servers/slapd/back-ldbm/Make-template b/servers/slapd/back-ldbm/Make-template index 51ef7a8171..cd5084cb10 100644 --- a/servers/slapd/back-ldbm/Make-template +++ b/servers/slapd/back-ldbm/Make-template @@ -20,21 +20,21 @@ 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) $(THREADS) +DEFINES = $(DEFS) $(LDAP_CRYPT) $(THREADS) CFLAGS = $(INCLUDES) $(THREADSINCLUDE) $(DEFINES) $(ACFLAGS) -LDFLAGS = -L$(LDIR) $(KRBLIBFLAG) +LDFLAGS = -L$(LDIR) $(KRBLIBFLAG) $(LDAP_CRYPT_LIB) all: FORCE -@echo "$(SLAPD_BACKENDS)" | grep LDAP_LDBM 2>&1 > /dev/null; \ if [ $$? = 0 ]; then \ - $(MAKE) $(MFLAGS) CC=$(CC) libback-ldbm.a; \ + $(MAKE) $(MFLAGS) CC="$(CC)" libback-ldbm.a; \ else \ echo "Include -DLDAP_LDBM in SLAPD_BACKENDS in the"; \ echo "Make-common file to build the ldbm backend"; \ @@ -69,80 +69,4 @@ depend: FORCE links: @$(LN) .src/*.[ch] . -# DO NOT DELETE THIS LINE -- mkdep uses it. -# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. -idl.o: idl.c ../slap.h ../../../include/avl.h ../../../include/lber.h -idl.o: ../../../include/ldap.h ../../../include/lthread.h -idl.o: ../../../include/ldif.h ../../../include/ldapconfig.h back-ldbm.h -idl.o: ../../../include/ldbm.h -add.o: add.c ../slap.h ../../../include/avl.h ../../../include/lber.h -add.o: ../../../include/ldap.h ../../../include/lthread.h -add.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -search.o: search.c ../slap.h ../../../include/avl.h ../../../include/lber.h -search.o: ../../../include/ldap.h ../../../include/lthread.h -search.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -cache.o: cache.c ../slap.h ../../../include/avl.h ../../../include/lber.h -cache.o: ../../../include/ldap.h ../../../include/lthread.h -cache.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -dbcache.o: dbcache.c ../../../include/portable.h ../slap.h -dbcache.o: ../../../include/avl.h ../../../include/lber.h -dbcache.o: ../../../include/ldap.h ../../../include/lthread.h -dbcache.o: ../../../include/ldif.h ../../../include/ldapconfig.h back-ldbm.h -dbcache.o: ../../../include/ldbm.h -dn2id.o: dn2id.c ../slap.h ../../../include/avl.h ../../../include/lber.h -dn2id.o: ../../../include/ldap.h ../../../include/lthread.h -dn2id.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -id2entry.o: id2entry.c ../slap.h ../../../include/avl.h ../../../include/lber.h -id2entry.o: ../../../include/ldap.h ../../../include/lthread.h -id2entry.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -index.o: index.c ../slap.h ../../../include/avl.h ../../../include/lber.h -index.o: ../../../include/ldap.h ../../../include/lthread.h -index.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -id2children.o: id2children.c ../slap.h ../../../include/avl.h -id2children.o: ../../../include/lber.h ../../../include/ldap.h -id2children.o: ../../../include/lthread.h ../../../include/ldif.h back-ldbm.h -id2children.o: ../../../include/ldbm.h -nextid.o: nextid.c ../slap.h ../../../include/avl.h ../../../include/lber.h -nextid.o: ../../../include/ldap.h ../../../include/lthread.h -nextid.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -abandon.o: abandon.c -compare.o: compare.c ../slap.h ../../../include/avl.h ../../../include/lber.h -compare.o: ../../../include/ldap.h ../../../include/lthread.h -compare.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -modify.o: modify.c ../slap.h ../../../include/avl.h ../../../include/lber.h -modify.o: ../../../include/ldap.h ../../../include/lthread.h -modify.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -modrdn.o: modrdn.c ../slap.h ../../../include/avl.h ../../../include/lber.h -modrdn.o: ../../../include/ldap.h ../../../include/lthread.h -modrdn.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -delete.o: delete.c ../slap.h ../../../include/avl.h ../../../include/lber.h -delete.o: ../../../include/ldap.h ../../../include/lthread.h -delete.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -init.o: init.c ../slap.h ../../../include/avl.h ../../../include/lber.h -init.o: ../../../include/ldap.h ../../../include/lthread.h -init.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -config.o: config.c ../slap.h ../../../include/avl.h ../../../include/lber.h -config.o: ../../../include/ldap.h ../../../include/lthread.h -config.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -bind.o: bind.c ../slap.h ../../../include/avl.h ../../../include/lber.h -bind.o: ../../../include/ldap.h ../../../include/lthread.h -bind.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -attr.o: attr.c ../slap.h ../../../include/avl.h ../../../include/lber.h -attr.o: ../../../include/ldap.h ../../../include/lthread.h -attr.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -filterindex.o: filterindex.c ../slap.h ../../../include/avl.h -filterindex.o: ../../../include/lber.h ../../../include/ldap.h -filterindex.o: ../../../include/lthread.h ../../../include/ldif.h back-ldbm.h -filterindex.o: ../../../include/ldbm.h -unbind.o: unbind.c ../slap.h ../../../include/avl.h ../../../include/lber.h -unbind.o: ../../../include/ldap.h ../../../include/lthread.h -unbind.o: ../../../include/ldif.h -kerberos.o: kerberos.c ../slap.h ../../../include/avl.h ../../../include/lber.h -kerberos.o: ../../../include/ldap.h ../../../include/lthread.h -kerberos.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h -close.o: close.c ../slap.h ../../../include/avl.h ../../../include/lber.h -close.o: ../../../include/ldap.h ../../../include/lthread.h -close.o: ../../../include/ldif.h back-ldbm.h ../../../include/ldbm.h - -# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/servers/slapd/back-ldbm/group.c b/servers/slapd/back-ldbm/group.c new file mode 100644 index 0000000000..49161fc55b --- /dev/null +++ b/servers/slapd/back-ldbm/group.c @@ -0,0 +1,90 @@ +/* compare.c - ldbm backend compare routine */ + +#include +#include +#include +#include +#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 + diff --git a/servers/slapd/back-ldbm/idl.c b/servers/slapd/back-ldbm/idl.c index 60828a2610..1a76ff8350 100644 --- a/servers/slapd/back-ldbm/idl.c +++ b/servers/slapd/back-ldbm/idl.c @@ -2,7 +2,6 @@ #include #include -#include #include "slap.h" #include "ldapconfig.h" #include "back-ldbm.h" @@ -164,15 +163,18 @@ idl_store( IDList *idl ) { - int rc; + int rc, flags; Datum data; + struct ldbminfo *li = (struct ldbminfo *) be->be_private; /* Debug( LDAP_DEBUG_TRACE, "=> idl_store\n", 0, 0, 0 ); */ data.dptr = (char *) idl; data.dsize = (2 + idl->b_nmax) * sizeof(ID); - - rc = ldbm_cache_store( db, key, data, LDBM_REPLACE ); + + 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 ); */ return( rc ); @@ -726,12 +728,9 @@ idl_notin( if ( a == NULL ) { return( NULL ); } - if ( b == NULL ) { + if ( b == NULL || ALLIDS( b )) { return( idl_dup( a ) ); } - if ( ALLIDS( b ) ) { - return( NULL ); - } if ( ALLIDS( a ) ) { n = idl_alloc( SLAPD_LDBM_MIN_MAXIDS ); diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 998bfa8c6a..c0e32b12d1 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -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; } @@ -231,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 diff --git a/servers/slapd/filterentry.c b/servers/slapd/filterentry.c index 712ff22e2e..3aa261751f 100644 --- a/servers/slapd/filterentry.c +++ b/servers/slapd/filterentry.c @@ -4,22 +4,13 @@ #include #include #include -#ifdef sunos5 -#include "regexpr.h" -#else -#include "regex.h" -#endif +#include #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(); @@ -223,11 +214,12 @@ test_approx_filter( w2 = next_word( w2 ) ) { c2 = phonetic( w2 ); if ( strcmp( c1, c2 ) == 0 ) { + free( c2 ); break; } + free( c2 ); } free( c1 ); - free( c2 ); /* * if we stopped because we ran out of words @@ -322,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 ); @@ -389,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 ); - 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 ); + 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 ); } -#endif /* sunos5 */ /* for each value in the attribute see if regex matches */ for ( i = 0; a->a_vals[i] != NULL; i++ ) { @@ -417,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 ); diff --git a/servers/slapd/init.c b/servers/slapd/init.c index 03dd850f0e..94c47b4143 100644 --- a/servers/slapd/init.c +++ b/servers/slapd/init.c @@ -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 } diff --git a/servers/slapd/main.c b/servers/slapd/main.c index 01930b9709..8229fbf26b 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -10,16 +10,17 @@ #include "slap.h" #include "ldapconfig.h" -extern void daemon(); +extern void slapd_daemon(); extern int lber_debug; extern char Versionstr[]; + /* * read-only global variables or variables only written by the listener * thread (after they are initialized) - no need to protect them with a mutex. */ -int ldap_debug; +int ldap_debug = 0; #ifdef LDAP_DEBUG int ldap_syslog = LDAP_DEBUG_STATS; #else @@ -55,15 +56,12 @@ 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 ) char *name; { - fprintf( stderr, "usage: %s [-d debuglevel] [-f configfile] [-p portnumber] [-s sysloglevel]\n", name ); + fprintf( stderr, "usage: %s [-d ?|debuglevel] [-f configfile] [-p portnumber] [-s sysloglevel]\n", name ); } main( argc, argv ) @@ -105,19 +103,19 @@ main( argc, argv ) LDAP_DEBUG_CONFIG ); printf( "\tLDAP_DEBUG_ACL\t\t%d\n", LDAP_DEBUG_ACL ); - printf( "\tLDAP_DEBUG_STATS\t\t%d\n", + printf( "\tLDAP_DEBUG_STATS\t%d\n", LDAP_DEBUG_STATS ); - printf( "\tLDAP_DEBUG_STATS2\t\t%d\n", + printf( "\tLDAP_DEBUG_STATS2\t%d\n", LDAP_DEBUG_STATS2 ); - printf( "\tLDAP_DEBUG_SHELL\t\t%d\n", + printf( "\tLDAP_DEBUG_SHELL\t%d\n", LDAP_DEBUG_SHELL ); - printf( "\tLDAP_DEBUG_PARSE\t\t%d\n", + printf( "\tLDAP_DEBUG_PARSE\t%d\n", LDAP_DEBUG_PARSE ); printf( "\tLDAP_DEBUG_ANY\t\t%d\n", LDAP_DEBUG_ANY ); exit( 0 ); } else { - ldap_debug = atoi( optarg ); + ldap_debug |= atoi( optarg ); lber_debug = (ldap_debug & LDAP_DEBUG_BER); } break; @@ -184,12 +182,27 @@ main( argc, argv ) pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); - if ( pthread_create( &listener_tid, attr, (void *) daemon, +#ifndef THREAD_MIT_PTHREADS + /* POSIX_THREADS or compatible + * This is a draft 10 or standard pthreads implementation + */ + if ( pthread_create( &listener_tid, &attr, (void *) slapd_daemon, + (void *) port ) != 0 ) { + Debug( LDAP_DEBUG_ANY, + "listener pthread_create failed\n", 0, 0, 0 ); + exit( 1 ); + } +#else /* !THREAD_MIT_PTHREADS */ + /* + * This is a draft 4 or earlier pthreads implementation + */ + if ( pthread_create( &listener_tid, attr, (void *) slapd_daemon, (void *) port ) != 0 ) { Debug( LDAP_DEBUG_ANY, "listener pthread_create failed\n", 0, 0, 0 ); exit( 1 ); } +#endif /* !THREAD_MIT_PTHREADS */ pthread_attr_destroy( &attr ); pthread_join( listener_tid, (void *) &status ); pthread_exit( 0 ); diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index a1ff6e5e75..300b76aa6b 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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 ); diff --git a/servers/slapd/regex.c b/servers/slapd/regex.c deleted file mode 100644 index 42d2f4152e..0000000000 --- a/servers/slapd/regex.c +++ /dev/null @@ -1,909 +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. - * - * Modification history: - * - * $Log: regex.c,v $ - * 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 */ diff --git a/servers/slapd/result.c b/servers/slapd/result.c index 0ef82a7b3e..b8e5c85059 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -121,7 +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 ); @@ -192,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 ); @@ -202,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 ); } @@ -220,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; } @@ -248,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; } @@ -270,6 +300,7 @@ send_search_entry( send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, "ber_printf value" ); + free(edn); return( 1 ); } } @@ -280,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, "}}}}" ); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index bf0c9c8297..a5df09b0e3 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -6,6 +6,9 @@ #define LDAP_SYSLOG #include +#include +#include + #include "avl.h" #include "lber.h" #include "ldap.h" @@ -17,6 +20,9 @@ #define ON 1 #define OFF (-1) +#define UNDEFINED 0 + +#define MAXREMATCHES 10 /* * represents an attribute value assertion (i.e., attr=value) @@ -121,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 @@ -134,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; @@ -187,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; /* diff --git a/servers/slapd/tools/Make-template b/servers/slapd/tools/Make-template index 112c4abbd8..b5c3c17d3e 100644 --- a/servers/slapd/tools/Make-template +++ b/servers/slapd/tools/Make-template @@ -24,15 +24,15 @@ 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) $(SERVERDEFS) $(THREADS) +DEFINES = $(DEFS) $(LDAP_CRYPT) $(SERVERDEFS) $(THREADS) CFLAGS = $(INCLUDES) $(DEFINES) $(ACFLAGS) LDFLAGS = -L$(LDIR) $(EXLDFLAGS) LIBS = -lldif -lldap -llber -lldbm -lavl $(LDBMLIB) $(EXLIBS) $(ALIBS) LIBS2 = -lldif -lldbm -lavl $(LDBMLIB) -llber $(KRBLIBFLAG) $(KRBLIBS) \ - -llthread $(THREADSLIB) $(ALIBS) + -llthread $(THREADSLIB) $(ALIBS) $(LDAP_CRYPT_LIB) all: build-edb2ldif ldif2index ldif2ldbm ldbmcat ldif2id2entry \ ldif2id2children centipede ldbmtest ldif @@ -73,13 +73,10 @@ ldif2index: ldif2index.o ../libbackends.a $(OBJS2) $(CC) $(ALDFLAGS) -o $@ ldif2index.o $(OBJS2) \ ../libbackends.a $(LDFLAGS) $(LIBS2) -ldif2ldbm: ldif2ldbm.sed.o ../libbackends.a $(OBJS2) - $(CC) $(ALDFLAGS) -o $@ ldif2ldbm.sed.o $(OBJS2) \ +ldif2ldbm: ldif2ldbm.o ../libbackends.a $(OBJS2) + $(CC) $(ALDFLAGS) -o $@ ldif2ldbm.o $(OBJS2) \ ../libbackends.a $(LDFLAGS) $(LIBS2) -ldif2ldbm.sed.c: ldif2ldbm.c - $(SED) -e 's;%ETCDIR%;$(RUNTIMEETCDIR);' ldif2ldbm.c > ldif2ldbm.sed.c - ldif2id2entry: ldif2id2entry.o ../libbackends.a $(OBJS2) $(CC) $(ALDFLAGS) -o $@ ldif2id2entry.o $(OBJS2) \ ../libbackends.a $(LDFLAGS) $(LIBS2) @@ -106,49 +103,49 @@ ldbmtest: ldbmtest.o ../libbackends.a $(OBJS2) $(CC) $(ALDFLAGS) -o ldbmtest ldbmtest.o $(OBJS2) \ ../libbackends.a $(LDFLAGS) $(LIBS2) -install: $(ETCDIR) $(ETCDIR)/edb2ldif $(ETCDIR)/ldif2ldbm \ - $(ETCDIR)/ldif2index $(ETCDIR)/ldif2id2entry \ - $(ETCDIR)/ldif2id2children $(ETCDIR)/ldbmcat \ - $(ETCDIR)/centipede $(ETCDIR)/ldbmtest \ - $(ETCDIR)/ldif +install: $(LDAP_SBINDIR) $(LDAP_SBINDIR)/edb2ldif $(LDAP_SBINDIR)/ldif2ldbm \ + $(LDAP_SBINDIR)/ldif2index $(LDAP_SBINDIR)/ldif2id2entry \ + $(LDAP_SBINDIR)/ldif2id2children $(LDAP_SBINDIR)/ldbmcat \ + $(LDAP_SBINDIR)/centipede $(LDAP_SBINDIR)/ldbmtest \ + $(LDAP_SBINDIR)/ldif -$(ETCDIR)/edb2ldif: build-edb2ldif +$(LDAP_SBINDIR)/edb2ldif: build-edb2ldif @if [ "$(HAVEISODE)" = "yes" ]; then \ - $(INSTALL) $(INSTALLFLAGS) -m 755 edb2ldif $(ETCDIR); \ + $(INSTALL) $(INSTALLFLAGS) -m 755 edb2ldif $(LDAP_SBINDIR); \ else \ exit 0; \ fi -$(ETCDIR)/chlog2replog: build-chlog2replog +$(LDAP_SBINDIR)/chlog2replog: build-chlog2replog @if [ "$(HAVEISODE)" = "yes" ]; then \ - $(INSTALL) $(INSTALLFLAGS) -m 755 chlog2replog $(ETCDIR); \ + $(INSTALL) $(INSTALLFLAGS) -m 755 chlog2replog $(LDAP_SBINDIR); \ else \ exit 0; \ fi -$(ETCDIR)/ldif2ldbm: ldif2ldbm - $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2ldbm $(ETCDIR) +$(LDAP_SBINDIR)/ldif2ldbm: ldif2ldbm + $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2ldbm $(LDAP_SBINDIR) -$(ETCDIR)/ldif2index: ldif2index - $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2index $(ETCDIR) +$(LDAP_SBINDIR)/ldif2index: ldif2index + $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2index $(LDAP_SBINDIR) -$(ETCDIR)/ldif2id2entry: ldif2id2entry - $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2id2entry $(ETCDIR) +$(LDAP_SBINDIR)/ldif2id2entry: ldif2id2entry + $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2id2entry $(LDAP_SBINDIR) -$(ETCDIR)/ldif2id2children: ldif2id2children - $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2id2children $(ETCDIR) +$(LDAP_SBINDIR)/ldif2id2children: ldif2id2children + $(INSTALL) $(INSTALLFLAGS) -m 755 ldif2id2children $(LDAP_SBINDIR) -$(ETCDIR)/ldbmcat: ldbmcat - $(INSTALL) $(INSTALLFLAGS) -m 755 ldbmcat $(ETCDIR) +$(LDAP_SBINDIR)/ldbmcat: ldbmcat + $(INSTALL) $(INSTALLFLAGS) -m 755 ldbmcat $(LDAP_SBINDIR) -$(ETCDIR)/ldif: ldif - $(INSTALL) $(INSTALLFLAGS) -m 755 ldif $(ETCDIR) +$(LDAP_SBINDIR)/ldif: ldif + $(INSTALL) $(INSTALLFLAGS) -m 755 ldif $(LDAP_SBINDIR) -$(ETCDIR)/centipede: centipede - $(INSTALL) $(INSTALLFLAGS) -m 755 centipede $(ETCDIR) +$(LDAP_SBINDIR)/centipede: centipede + $(INSTALL) $(INSTALLFLAGS) -m 755 centipede $(LDAP_SBINDIR) -$(ETCDIR)/ldbmtest: ldbmtest - $(INSTALL) $(INSTALLFLAGS) -m 755 ldbmtest $(ETCDIR) +$(LDAP_SBINDIR)/ldbmtest: ldbmtest + $(INSTALL) $(INSTALLFLAGS) -m 755 ldbmtest $(LDAP_SBINDIR) lint: FORCE $(LINT) $(INCLUDES) $(DEFINES) $(SRCS) @@ -160,60 +157,17 @@ clean: FORCE @echo "making clean in `$(PWD)`" $(RM) edb2ldif ldif2index *.o core a.out edb2-vers.c \ ldif2ldbm ldif2id2entry ldif2id2children ldbmcat ldif \ - centipede chlog2replog sizecount ldif2ldbm.sed.c ldbmtest + centipede chlog2replog sizecount ldbmtest -depend: ldif2ldbm.sed.c FORCE +depend: FORCE @if [ ! -z "$(HAVEISODE)" ]; then \ DEPENDEXTRAS="$(ISODEINCLUDEFLAG) chlog2replog.c $(EDB2LDIFSRCS)"; \ fi; \ $(MKDEP) $(INCLUDES) $(DEFINES) $$DEPENDEXTRAS ldif2index.c \ ldif2ldbm.c ldif2id2entry.c ldif2id2children.c ldbmcat.c \ - centipede.c sizecount.c ldif2ldbm.sed.c ldbmtest.c ldif.c + centipede.c sizecount.c ldbmtest.c ldif.c links: @echo "making links in `$(PWD)`" @$(LN) .src/*.[ch] . - -# DO NOT DELETE THIS LINE -- mkdep uses it. -# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. - -chlog2replog.o: chlog2replog.c ../../../include/ldif.h -edb2ldif.o: edb2ldif.c -ldapsyntax.o: ldapsyntax.c ../../../include/lber.h ../../../include/ldap.h -ldapsyntax.o: ../../../include/ldif.h ldapsyntax.h -ldif2index.o: ldif2index.c ../slap.h ../../../include/avl.h -ldif2index.o: ../../../include/lber.h ../../../include/ldap.h -ldif2index.o: ../../../include/lthread.h ../../../include/ldif.h -ldif2ldbm.o: ldif2ldbm.c ../slap.h ../../../include/avl.h -ldif2ldbm.o: ../../../include/lber.h ../../../include/ldap.h -ldif2ldbm.o: ../../../include/lthread.h ../../../include/ldif.h -ldif2ldbm.o: ../back-ldbm/back-ldbm.h ../../../include/ldbm.h -ldif2id2entry.o: ldif2id2entry.c ../slap.h ../../../include/avl.h -ldif2id2entry.o: ../../../include/lber.h ../../../include/ldap.h -ldif2id2entry.o: ../../../include/lthread.h ../../../include/ldif.h -ldif2id2entry.o: ../back-ldbm/back-ldbm.h ../../../include/ldbm.h -ldif2id2children.o: ldif2id2children.c ../slap.h ../../../include/avl.h -ldif2id2children.o: ../../../include/lber.h ../../../include/ldap.h -ldif2id2children.o: ../../../include/lthread.h ../../../include/ldif.h -ldif2id2children.o: ../back-ldbm/back-ldbm.h ../../../include/ldbm.h -ldbmcat.o: ldbmcat.c ../../../include/ldbm.h ../slap.h ../../../include/avl.h -ldbmcat.o: ../../../include/lber.h ../../../include/ldap.h -ldbmcat.o: ../../../include/lthread.h ../../../include/ldif.h -centipede.o: centipede.c ../../../include/lber.h ../../../include/ldap.h -centipede.o: ../../../include/ldapconfig.h ../../../include/ldbm.h -sizecount.o: sizecount.c ../../../include/ldbm.h ../../../include/lber.h -sizecount.o: ../../../include/ldap.h ../../../include/portable.h -ldif2ldbm.sed.o: ldif2ldbm.sed.c ../slap.h ../../../include/avl.h -ldif2ldbm.sed.o: ../../../include/lber.h ../../../include/ldap.h -ldif2ldbm.sed.o: ../../../include/lthread.h ../../../include/ldif.h -ldif2ldbm.sed.o: ../back-ldbm/back-ldbm.h ../../../include/ldbm.h -ldbmtest.o: ldbmtest.c ../../../include/portable.h -ldbmtest.o: ../../../include/ldapconfig.h ../slap.h ../../../include/avl.h -ldbmtest.o: ../../../include/lber.h ../../../include/ldap.h -ldbmtest.o: ../../../include/lthread.h ../../../include/ldif.h -ldbmtest.o: ../back-ldbm/back-ldbm.h ../../../include/ldbm.h -ldif.o: ldif.c ../../../include/lber.h ../../../include/ldap.h -ldif.o: ../../../include/ldif.h - -# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/tests/data/acl.out.master b/tests/data/acl.out.master index 4bef01e521..1a8074d702 100644 --- a/tests/data/acl.out.master +++ b/tests/data/acl.out.master @@ -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 diff --git a/tests/scripts/acfilter.sh b/tests/scripts/acfilter.sh new file mode 100755 index 0000000000..a7c6ac5ed8 --- /dev/null +++ b/tests/scripts/acfilter.sh @@ -0,0 +1,2 @@ +#!/bin/sh +egrep -iv '^modifiersname:|^modifytimestamp:|^creatorsname:|^createtimestamp' diff --git a/tests/scripts/test002-populate b/tests/scripts/test002-populate index c04d1f5f65..bf01845fd8 100755 --- a/tests/scripts/test002-populate +++ b/tests/scripts/test002-populate @@ -5,10 +5,10 @@ echo "Cleaning up in $DBDIR..." -rm -f $DBDIR/* +rm -f $DBDIR/[^C]* echo "Starting slapd on TCP/IP port $PORT..." -$SLAPD -f $CONF -p $PORT -d 1 > /dev/null 2>&1 & +$SLAPD -f $CONF -p $PORT -d 1 > $MASTERLOG 2>&1 & PID=$! echo "Using ldapsearch to check that slapd is running..." @@ -44,8 +44,13 @@ if [ $RC != 0 ]; then exit $RC fi -echo "Comparing retrieved entries to LDIF file used to create database" -cmp $SEARCHOUT $LDIF +echo "Filtering ldapsearch results..." +. scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT +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 diff --git a/tests/scripts/test006-acls b/tests/scripts/test006-acls index ec1c964d10..a9b1b4c519 100755 --- a/tests/scripts/test006-acls +++ b/tests/scripts/test006-acls @@ -4,7 +4,7 @@ echo "Cleaning up in $DBDIR..." -rm -f $DBDIR/* +rm -f $DBDIR/[^C]* echo "Running ldif2ldbm to build slapd database..." $LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools @@ -15,7 +15,7 @@ if [ $RC != 0 ]; then fi echo "Starting slapd on TCP/IP port $PORT..." -$SLAPD -f $ACLCONF -p $PORT -d 1 > /dev/null 2>&1 & +$SLAPD -f $ACLCONF -p $PORT -d 1 > $MASTERLOG 2>&1 & PID=$! echo "Testing slapd access control..." @@ -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 -- 2.47.2