diff options
author | Noriko Hosoi <nhosoi@kiki.usersys.redhat.com> | 2009-05-28 09:55:06 -0700 |
---|---|---|
committer | Noriko Hosoi <nhosoi@kiki.usersys.redhat.com> | 2009-05-28 09:55:06 -0700 |
commit | 67aca96ae2c53f74f896439840a82cbccbeb34cf (patch) | |
tree | ba1da5996985d5990ca5cb13db118983e6b85b2c /ldap/servers | |
parent | 586da77caf36591a261506e89dcc9e6a4db00036 (diff) | |
download | ds-67aca96ae2c53f74f896439840a82cbccbeb34cf.tar.gz ds-67aca96ae2c53f74f896439840a82cbccbeb34cf.tar.xz ds-67aca96ae2c53f74f896439840a82cbccbeb34cf.zip |
Use thread aware library for complex regex searches
For more details, see the design doc at http://directory.fedoraproject.org/wiki/Thread_Aware_Regex
Additional 2 unrelated changes are being made:
1) dbgen.pl.in: secretary and manager are having a dn format value "cn=...".
2) slapi_counter_sunos_sparcv9.S: adding "#define _ASM 1" to force to set an assembler code macro _ASM.
Diffstat (limited to 'ldap/servers')
-rw-r--r-- | ldap/servers/plugins/acl/acl.c | 27 | ||||
-rw-r--r-- | ldap/servers/plugins/syntaxes/string.c | 14 | ||||
-rw-r--r-- | ldap/servers/slapd/getfilelist.c | 18 | ||||
-rw-r--r-- | ldap/servers/slapd/init.c | 2 | ||||
-rw-r--r-- | ldap/servers/slapd/proto-slap.h | 7 | ||||
-rw-r--r-- | ldap/servers/slapd/regex.c | 1256 | ||||
-rw-r--r-- | ldap/servers/slapd/sasl_map.c | 80 | ||||
-rw-r--r-- | ldap/servers/slapd/slap.h | 7 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi-plugin.h | 48 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi-private.h | 7 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi_counter_sunos_sparcv9.S | 1 | ||||
-rwxr-xr-x | ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in | 10 |
12 files changed, 303 insertions, 1174 deletions
diff --git a/ldap/servers/plugins/acl/acl.c b/ldap/servers/plugins/acl/acl.c index 6e435559..f7f58650 100644 --- a/ldap/servers/plugins/acl/acl.c +++ b/ldap/servers/plugins/acl/acl.c @@ -3141,12 +3141,13 @@ int acl_match_substring ( Slapi_Filter *f, char *str, int exact_match) { int i, rc, len; - char *p; + char *p = NULL; char *end, *realval, *tmp; char pat[BUFSIZ]; char buf[BUFSIZ]; char *type, *initial, *final; char **any; + Slapi_Regex *re = NULL; if ( 0 != slapi_filter_get_subfilt ( f, &type, &initial, &any, &final ) ) { return (ACL_FALSE); @@ -3234,29 +3235,21 @@ acl_match_substring ( Slapi_Filter *f, char *str, int exact_match) ** Now we will compile the pattern and compare wth the string to ** see if the input string matches with the patteren or not. */ - slapd_re_lock(); - if ((p = slapd_re_comp (pat)) != 0) { + p = NULL; + re = slapi_re_comp( pat, &p ); + if (NULL == re) { slapi_log_error (SLAPI_LOG_ACL, plugin_name, - "acl_match_substring:re_comp failed (%s)\n", p); - slapd_re_unlock(); + "acl_match_substring:re_comp failed (%s)\n", p?p:"unknown"); return (ACL_ERR); } - /* re_exec() returns 1 if the string p1 matches the last compiled + /* slapi_re_exec() returns 1 if the string p1 matches the last compiled ** regular expression, 0 if the string p1 failed to match - ** (see man pages) - ** - ** IMPORTANT NOTE: If I use compile() and step() to do the patteren - ** matching, it seems that step() is leaking 1036 bytes/search - ** I couldn't figure out why it's leaking. */ - rc = slapd_re_exec( realval, -1 /* no timelimit */ ); - - slapd_re_unlock(); + rc = slapi_re_exec( re, realval, -1 /* no timelimit */ ); - if (tmp != NULL) { - slapi_ch_free ( (void **) &tmp ); - } + slapi_re_free(re); + slapi_ch_free ( (void **) &tmp ); if (rc == 1) { return ACL_TRUE; diff --git a/ldap/servers/plugins/syntaxes/string.c b/ldap/servers/plugins/syntaxes/string.c index 138d98af..218cc762 100644 --- a/ldap/servers/plugins/syntaxes/string.c +++ b/ldap/servers/plugins/syntaxes/string.c @@ -208,7 +208,8 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, time_t time_up = 0; time_t optime = 0; /* time op was initiated */ int timelimit = 0; /* search timelimit */ - Operation *op = NULL; + Operation *op = NULL; + Slapi_Regex *re = NULL; LDAPDebug( LDAP_DEBUG_FILTER, "=> string_filter_sub\n", 0, 0, 0 ); @@ -284,10 +285,11 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, /* compile the regex */ p = (bigpat) ? bigpat : pat; - slapd_re_lock(); - if ( (tmpbuf = slapd_re_comp( p )) != 0 ) { + tmpbuf = NULL; + re = slapi_re_comp( p, &tmpbuf ); + if (NULL == re) { LDAPDebug( LDAP_DEBUG_ANY, "re_comp (%s) failed (%s): %s\n", - pat, p, tmpbuf ); + pat, p, tmpbuf?tmpbuf:"unknown" ); rc = LDAP_OPERATIONS_ERROR; goto bailout; } else { @@ -326,7 +328,7 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, } value_normalize( realval, syntax, 1 /* trim leading blanks */ ); - tmprc = slapd_re_exec( realval, time_up ); + tmprc = slapi_re_exec( re, realval, time_up ); LDAPDebug( LDAP_DEBUG_TRACE, "re_exec (%s) %i\n", escape_string( realval, ebuf ), tmprc, 0 ); @@ -339,7 +341,7 @@ string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final, } } bailout: - slapd_re_unlock(); + slapi_re_free(re); slapi_ch_free((void**)&tmpbuf ); /* NULL is fine */ slapi_ch_free((void**)&bigpat ); /* NULL is fine */ diff --git a/ldap/servers/slapd/getfilelist.c b/ldap/servers/slapd/getfilelist.c index 08619056..b2ef6e21 100644 --- a/ldap/servers/slapd/getfilelist.c +++ b/ldap/servers/slapd/getfilelist.c @@ -122,16 +122,20 @@ is_a_file(const char *dirname, const char *filename) static int matches(const char *filename, const char *pattern) { + Slapi_Regex *re = NULL; int match = 0; - char *s = 0; + char *error = NULL; + if (!pattern) return 1; /* null pattern matches everything */ - slapd_re_lock(); - s = slapd_re_comp((char *)pattern); - if (!s) - match = slapd_re_exec((char *)filename, -1 /* no timelimit */); - slapd_re_unlock(); + /* Compile the pattern */ + re = slapi_re_comp( (char *)pattern, &error ); + if (re) { + /* Matches the compiled pattern against the filename */ + match = slapi_re_exec( re, filename, -1 /* no time limit */ ); + slapi_re_free( re ); + } return match; } @@ -188,7 +192,7 @@ get_filelist( if (nodirs && is_a_dir(dirname, dirent->name)) continue; - if (matches(dirent->name, pattern)) { + if (1 == matches(dirent->name, pattern)) { /* this strdup is free'd by free_string */ char *newone = slapi_ch_strdup(dirent->name); avl_insert(&filetree, newone, strcmp, 0); diff --git a/ldap/servers/slapd/init.c b/ldap/servers/slapd/init.c index 174e8ca6..3bf0ea24 100644 --- a/ldap/servers/slapd/init.c +++ b/ldap/servers/slapd/init.c @@ -76,8 +76,6 @@ slapd_init() num_conns = slapi_counter_new(); g_set_current_conn_count_mutex( PR_NewLock() ); - slapd_re_init(); - if ( g_get_current_conn_count_mutex() == NULL ) { LDAPDebug( LDAP_DEBUG_ANY, diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h index ba18a29c..41c80b59 100644 --- a/ldap/servers/slapd/proto-slap.h +++ b/ldap/servers/slapd/proto-slap.h @@ -1092,11 +1092,6 @@ Slapi_Backend *defbackend_get_backend( void ); void do_disconnect_server( Connection *conn, PRUint64 opconnid, int opid ); /* - * regex.c - */ -int re_init( void ); - -/* * secpwd.c */ char* getPassword(); @@ -1184,7 +1179,7 @@ int plugin_get_log_audit (const struct slapdplugin *plugin); */ char **get_filelist( const char *dirname, /* directory path; if NULL, uses "." */ - const char *pattern, /* grep (not shell!) file pattern regex */ + const char *pattern, /* regex pattern, not shell style wildcard */ int hiddenfiles, /* if true, return hidden files and directories too */ int nofiles, /* if true, do not return files */ int nodirs /* if true, do not return directories */ diff --git a/ldap/servers/slapd/regex.c b/ldap/servers/slapd/regex.c index f172edf2..9746aa03 100644 --- a/ldap/servers/slapd/regex.c +++ b/ldap/servers/slapd/regex.c @@ -31,8 +31,7 @@ * exception. * * - * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. - * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2009 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK **/ @@ -40,1121 +39,180 @@ # include <config.h> #endif -#include "slap.h" /* must come before regex.h */ -#include "portable.h" +/* number of elements in the output vector */ +#define OVECCOUNT 30 /* should be a multiple of 3; store up to \9 */ -#if defined( MACOS ) || defined( DOS ) || defined( _WIN32 ) || defined( NEED_BSDREGEX ) -#include "regex.h" +#include "slap.h" +#include "slapi-plugin.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.8 2009/01/12 18:14:57 nkinder - * Resolves: 174394 - * Summary: Make regex filter code handle empty values properly. - * - * Revision 1.7 2008/06/30 17:28:16 nhosoi - * Resoves: #448831 - * Summary: attacker can tie up CPU in regex code - * Description: when substring search is requested, sets the time limit based upon - * the nsslapd-timelimit value. Pass the timelimit (time_up) to the regular - * expression function. When the time is up, it returns the "Timelimit exceeded" - * error. Note: timelimit is applied non-Directory Manager users. - * - * Revision 1.6 2008/04/29 00:38:36 nhosoi - * Resolves: #182621 (#443955) - * Summary: Allow larger regex buffer to enable long substring filters - * Description: Applying the patches provided by ulf.weltman@hp.com. - * regex.c: use dynamically allocated regex buffer, use ptrdiff_t to store the offsets to be restored after the realloc, and use a constant for the value of "how much the NFA buffer can grow in one iteration on the pattern". - * string.c: use dynamically allocated buffer if the prepared buffer is not large enough, used wrong pointer (pat instead of p) in a debug message, and performed an unneeded strcat of ".*" - * - * Revision 1.5 2006/11/10 23:45:40 nhosoi - * Resolves: #214533 - * Summary: configure needs to support --with-fhs (Comment #6) - * Changes: Added the following include next to the end of the copyright block. - * + - * +#ifdef HAVE_CONFIG_H - * +# include <config.h> - * +#endif - * + - * - * Revision 1.4 2005/04/19 22:07:37 nkinder - * Fixed licensing typo - * - * Revision 1.3 2005/04/15 22:40:35 nkinder - * 155068 - Added license to source files - * - * Revision 1.2 2005/02/28 23:38:00 nkinder - * 149951 - Updated source code copyrights - * - * Revision 1.1.1.1 2005/01/21 00:40:51 cvsadm - * Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth) - * - * Revision 1.3.20.1.2.11 2005/01/14 01:22:12 nhosoi - * For the open-source project. - * 1) eliminated 'netsite' level - * 2) moved ns/config one level lower - * 3) moved fasttime to lib/base - * - * Revision 1.3.20.1.2.10 2004/10/01 18:46:09 dboreham - * Rename the built in regex functions to avoid colliding with the native OS versions, where presnet - * - * Revision 1.2 2004/10/01 06:29:11 david - * rename regex functions to avoid collision with native OS functions on Solaris - * - * Revision 1.1.1.1 2004/06/03 22:32:48 telackey - * Initial import Thu Jun 3 15:32:43 PDT 2004 - * - * Revision 1.3.20.1.2.9 2003/09/22 19:42:12 ulfw - * Update copyright years from 2001 to 2001-2003 - * - * Revision 1.3.20.1.2.8 2001/11/03 00:13:55 richm - * XXX use new copyright XXX - * - * Revision 1.3.20.1.2.7 2001/10/07 00:59:03 richm - * ldapserver/ldap/servers/slapd/regex.c - * 1.3.20.1.2.7 - * 20010918 - * - * Remove copyright caracter form copyright - * - * - * ==================================================== - * - * Revision 1.3.20.1.2.7 2001/09/18 11:43:06 rmarco - * Remove copyright caracter form copyright - * - * Revision 1.3.20.1.2.6 2001/02/13 09:45:16 rmarco - * copyrights - * - * Revision 1.3.20.1.2.5 1999/12/06 10:49:33 robey - * fix gcc warning - * - * Revision 1.3.20.1.2.4 1999/11/18 01:26:26 robey - * fix gcc warnings - * - * Revision 1.3.20.1.2.3 1999/08/20 23:13:33 merrells - * tidy up extern things - * - * Revision 1.3.20.1.2.2 1999/05/19 23:41:58 merrells - * Keep the Solaris compiler quiet - * - * Revision 1.3.20.1.2.1 1999/05/14 18:39:50 merrells - * value manipulation code extraction and reworking. - * - * Revision 1.3.20.1 1998/10/10 02:28:25 ggood - * Copy from Directory40RtmBranchpoint to DirectoryBranch - * - * Revision 1.3.10.5 1997/12/11 23:12:01 kristian - * fix bugs 97502, 97504 & 96569: handle 8-bit char's (especially UTF-8) correctly. - * - * Revision 1.3.10.4 1997/12/07 22:13:08 howes - * Always compile re_init(), re_lock(), and re_unlock(), even - * on platforms where we use the native regex stuff. - * - * Revision 1.3.10.3 1997/12/07 00:01:16 howes - * Add re_init(), re_lock(), and re_unlock() routines, to avoid race - * between acl and syntax code. - * - * Revision 1.3.10.2 1997/07/17 07:49:13 mcs - * merge changes made on ldapsdk_10_branch into server3_directory_branch - * - * Revision 1.3.10.1 1997/03/27 06:39:33 ggood - * Fix up more compiler warnings. - * - * Revision 1.3 1996/11/07 00:44:44 mcs - * eliminate a few compiler warnings - * - * Revision 1.2 1996/11/05 21:38:05 kristian - * copied from Directory_1996_11_04 - * - * Revision 1.1.1.1.2.1 1996/05/07 19:54:53 kristian - * Merged UMich ldap-3_3 into Dogbert - * - * Revision 1.1.1.2 1996/05/04 19:11:02 kristian - * UMich version 3.3 - * - * 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: - * The following three interfaces were added to avoid a race - * condition in slapd. The better long-term solution is to make - * the regex code thread-safe, by passing in the buffers needed. - * - * re_init: initializes the regex system. must be called - * before any other regex calls are made. - * - * re_lock: locks the regex system. must be called to avoid - * races between calls to re_comp and re_exec. - * - * re_unlock unlocks the regex system. must be called after - * a set of calls to re_comp and re_exec. - * - * 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 ... - */ - -/* This is the maximum the NFA buffer might grow for every op code processed. - The max seems to be the + after a character class, like "[a-z]+". It - needs 1 byte for the CCL code, 16 for the CCL bit map, and 2 for END codes - and 1 for a CLO code. */ -#define MAXOPSPACE 20 - -#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 +struct slapi_regex_handle { + pcre *re_pcre; /* contains the compiled pattern */ + int *re_ovector; /* output vector */ + int re_oveccount; /* count of the elements in output vector */ +}; -#define ASCIIB 0177 - -typedef unsigned char UCHAR; -/* char, on the other hand, may be signed or unsigned; - * it's platform-dependent. A hard fact of life, in C. - */ - -static int tagstk[MAXTAG]; /* subpat tag stack..*/ -static UCHAR *nfa = NULL; /* automaton.. */ -static int nfasize = MAXNFA; /* tracks size of nfa buffer */ -static int sta = NOP; /* status of lastpat */ - -static UCHAR bittab[BITBLK]; /* bit table for CCL */ - /* pre-set bits... */ -static UCHAR bitarr[] = {1,2,4,8,16,32,64,128}; - -#ifdef DEBUG -static void nfadump( UCHAR *ap); -#endif - -static void -chset(UCHAR c) -{ - bittab[((c) & (unsigned)BLKIND) >> 3] |= bitarr[(c) & BITIND]; -} - -#define badpat(x) (*nfa = END, x) -#define store(x) *mp++ = x - -char * -slapd_re_comp( char *pat ) -{ - register UCHAR *p; /* pattern pointer */ - register UCHAR *mp=nfa; /* nfa pointer */ - register UCHAR *lp; /* saved pointer.. */ - register UCHAR *sp=nfa; /* another one.. */ - - register int tagi = 0; /* tag stack index */ - register int tagc = 1; /* actual tag count */ - - register int n; - register UCHAR 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 = (UCHAR*)pat; *p; p++) { - /* Check if we are approaching end of nfa buffer. MAXOPSPACE is - the max we might add to the nfa per loop. */ - if (mp - (UCHAR*)nfa + MAXOPSPACE >= nfasize) { - /* Save offsets */ - ptrdiff_t mppos = mp - nfa; - ptrdiff_t sppos = sp - nfa; - - /* Double the nfa buffer size */ - nfasize *= 2; - nfa = (UCHAR*)slapi_ch_realloc((char*)nfa, nfasize); - - /* Restore pointers into realloced space */ - mp = nfa + mppos; - sp = nfa + sppos; - } - lp = mp; - switch(*p) { - - case '.': /* match any char.. */ - store(ANY); - break; - - case '^': /* match beginning.. */ - if (p == (UCHAR*)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((UCHAR)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++] = (UCHAR) 0) - store(mask ^ bittab[n]); - - break; - - case '*': /* match 0 or more.. */ - case '+': /* match 1 or more.. */ - if (p == (UCHAR*)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 UCHAR *bol; -static UCHAR *bopat[MAXTAG]; -static UCHAR *eopat[MAXTAG]; -#ifdef NEEDPROTOS -static UCHAR *pmatch( UCHAR *lp, UCHAR *ap, time_t time_up, int *err ); -#else /* NEEDPROTOS */ -static UCHAR *pmatch(); -#endif /* NEEDPROTOS */ - -/* - * re_exec: - * execute nfa to find a match. +/** + * Compiles a regular expression pattern. * - * 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. - * - * return values: 0 -- did not match - * 1 -- matched - * othersise -- ldap error (TIMELIMIT_EXCEEDED only) + * \param pat Pattern to be compiled. + * \param error The error string is set if the compile fails. + * \return This function returns a pointer to the regex handler which stores + * the compiled pattern. NULL if the compile fails. + * \warning The regex handler should be released by slapi_re_free(). */ - -int -slapd_re_exec( char *lp, time_t time_up ) +Slapi_Regex * +slapi_re_comp( char *pat, char **error ) { - register UCHAR c; - register UCHAR *ep = 0; - register UCHAR *ap = nfa; - int ldaperror = 0; - - bol = (UCHAR*)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((UCHAR*)lp,ap,time_up,&ldaperror); - break; - case CHR: /* ordinary char: locate it fast */ - c = *(ap+1); - while (*lp && *(UCHAR*)lp != c) - lp++; - if (!*lp) /* if EOS, fail, else fall thru. */ - return 0; - default: /* regular matching all the way. */ - do { - if ((ep = pmatch((UCHAR*)lp,ap,time_up,&ldaperror))) - break; - if (*lp) - lp++; - } while (*lp); - - break; - case END: /* munged automaton. fail always */ - return 0; - } - if (ldaperror) - return ldaperror; - if (!ep) - return 0; - - bopat[0] = (UCHAR*)lp; - eopat[0] = ep; - return 1; + Slapi_Regex *re_handle = NULL; + pcre *re = NULL; + const char *myerror = NULL; + int erroffset; + + re = pcre_compile(pat, 0, &myerror, &erroffset, NULL); + if (error) { + *error = myerror; + } + if (re) { + re_handle = (Slapi_Regex *)slapi_ch_calloc(sizeof(Slapi_Regex), 1); + re_handle->re_pcre = re; + } + + return re_handle; } -/* - * 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 -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 _ +/** + * Matches a compiled regular expression pattern against a given string. + * A thin wrapper of pcre_exec. + * + * \param re_handle The regex handler returned from slapi_re_comp. + * \param subject A string to be checked against the compiled pattern. + * \param time_up If the current time is larger than the value, this function + * returns immediately. (-1) means no time limit. + * \return This function returns 0 if the string did not match. + * \return This function returns 1 if the string matched. + * \return This function returns other values if any error occurred. + * \warning The regex handler should be released by slapi_re_free(). */ -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 UCHAR * -pmatch( UCHAR *lp, UCHAR *ap, time_t time_up, int *err ) +int +slapi_re_exec( Slapi_Regex *re_handle, char *subject, time_t time_up ) { - register int op, c, n; - register UCHAR *e; /* extra pointer for CLO */ - register UCHAR *bp; /* beginning of subpat.. */ - register UCHAR *ep; /* ending of subpat.. */ - UCHAR *are; /* to save the line ptr. */ - time_t curtime = current_time(); - - if ( time_up != -1 && curtime > time_up ) { - *err = LDAP_TIMELIMIT_EXCEEDED; - return 0; - } - - 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, time_up, err)) != NULL) - return e; - --lp; - } - return 0; - default: - re_fail("re_exec: bad nfa.", op); - return 0; - } - return lp; + int rc; + time_t curtime = current_time(); + + if (NULL == re_handle || NULL == re_handle->re_pcre || NULL == subject) { + return LDAP_PARAM_ERROR; + } + + if ( time_up != -1 && curtime > time_up ) { + return LDAP_TIMELIMIT_EXCEEDED; + } + + if (NULL == re_handle->re_ovector) { + re_handle->re_oveccount = OVECCOUNT; + re_handle->re_ovector = (int *)slapi_ch_malloc(sizeof(int) * OVECCOUNT); + } + + rc = pcre_exec( re_handle->re_pcre, /* the compiled pattern */ + NULL, /* no extra data */ + subject, /* the subject string */ + strlen(subject), /* the length of the subject */ + 0, /* start at offset 0 in the subject */ + 0, /* default options */ + re_handle->re_ovector, /* output vector for substring info */ + re_handle->re_oveccount ); /* number of elems in the ovector */ + + if (rc >= 0) { + return 1; /* matched */ + } else { + return 0; /* did not match */ + } + + return rc; } -/* - * 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] +/** + * Substitutes '&' or '\#' in the param src with the matched string. + * + * \param re_handle The regex handler returned from slapi_re_comp. + * \param subject A string checked against the compiled pattern. + * \param src A given string which could contain the substitution symbols. + * \param dst A pointer pointing to the memory which stores the output string. + * \param dstlen Size of the memory dst. + * \return This function returns 0 if the substitution was successful. + * \return This function returns -1 if the substitution failed. + * \warning The regex handler should be released by slapi_re_free(). */ - -static UCHAR deftab[16] = { - 0, 0, 0, 0, 0, 0, 0377, 003, 0376, 0377, 0377, 0207, - 0376, 0377, 0377, 007 -}; - -void -slapd_re_modw( char *s ) +int +slapi_re_subs( Slapi_Regex *re_handle, + char *subject, char *src, char **dst, unsigned long dstlen ) { - 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; + int thislen = 0; + int len = 0; + int pin; + int *ovector; + char *mydst = *dst; + char *substring_start; + char *p; + + if (NULL == src || NULL == re_handle || NULL == re_handle->re_ovector) { + memset(*dst, '\0', dstlen); + return -1; + } else if (NULL == dst || NULL == *dst || 0 == dstlen) { + return -1; + } + + ovector = re_handle->re_ovector; + + for (p = src; *p != NULL; p++) { + if ('&' == *p) { + if (re_handle->re_oveccount <= 1) { + memset(*dst, '\0', dstlen); + return -1; + } + substring_start = subject + ovector[0]; + thislen = ovector[1] - ovector[0]; + len += thislen; + } else if (('\\' == *p) && ('0' <= *(p+1) && *(p+1) <= '9')) { + pin = *(++p) - '0'; + if (re_handle->re_oveccount <= 2*pin+1) { + memset(*dst, '\0', dstlen); + return -1; + } + substring_start = subject + ovector[2*pin]; + thislen = ovector[2*pin+1] - ovector[2*pin]; + len += thislen; + } else { + substring_start = p; + thislen = 1; + len++; + } + if (len >= dstlen) { + int offset = mydst - *dst; + dstlen = len * 2; + *dst = (char *)slapi_ch_realloc(*dst, dstlen); + mydst = *dst + offset; + } + memcpy(mydst, substring_start, thislen); + mydst += thislen; + } + *mydst = '\0'; + return 0; } -/* - * re_subs: - * substitute the matched portions of the src in dst. - * - * & substitute the entire matched pattern. +/** + * Releases the regex handler which was returned from slapi_re_comp. * - * \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. + * \param re_handle The regex handler to be released. + * \return nothing */ -int -slapd_re_subs( char *src, char *dst) -{ - register char c; - register int pin; - register UCHAR *bp; - register UCHAR *ep; - - if (!*src || !bopat[0]) - return 0; - - while ((c = *src++) != 0) { - 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++ = *(char*)bp++; - if (bp < ep) - return 0; - } - } - *dst = (char) 0; - return 1; -} - -#ifdef DEBUG -/* - * symbolic - produce a symbolic dump of the nfa - */ -void -symbolic( char *s ) -{ - printf("pattern: %s\n", s); - printf("nfacode:\n"); - nfadump(nfa); -} - -static void -nfadump( UCHAR *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,(UCHAR)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 */ - -static PRLock *regex_mutex = NULL; - -int -slapd_re_init( void ) -{ - if ( NULL == regex_mutex ) { - regex_mutex = PR_NewLock(); - } - - if ( NULL == nfa ) { - nfa = (UCHAR*)slapi_ch_malloc( MAXNFA ); - } - - return( NULL == regex_mutex ? -1 : 0 ); -} - void -slapd_re_lock( void ) -{ - PR_ASSERT( NULL != regex_mutex ); - PR_Lock( regex_mutex ); -} - -int -slapd_re_unlock( void ) +slapi_re_free(Slapi_Regex *re_handle) { - PR_ASSERT( NULL != regex_mutex ); - return( PR_Unlock( regex_mutex ) ); + if (re_handle) { + if (re_handle->re_pcre) { + pcre_free(re_handle->re_pcre); + } + slapi_ch_free((void **)&re_handle->re_ovector); + slapi_ch_free((void **)&re_handle); + } } diff --git a/ldap/servers/slapd/sasl_map.c b/ldap/servers/slapd/sasl_map.c index 4e614c1f..10a0cf4a 100644 --- a/ldap/servers/slapd/sasl_map.c +++ b/ldap/servers/slapd/sasl_map.c @@ -443,44 +443,80 @@ sasl_map_first(sasl_map_private *priv) static int sasl_map_check(sasl_map_data *dp, char *sasl_user_and_realm, char **ldap_search_base, char **ldap_search_filter) { + Slapi_Regex *re = NULL; int ret = 0; int matched = 0; char *recomp_result = NULL; + LDAPDebug( LDAP_DEBUG_TRACE, "-> sasl_map_check\n", 0, 0, 0 ); - /* DBDB: currently using the rather old internal slapd regex library, which is not thread-safe */ - /* So lock it first */ - slapd_re_lock(); - /* Compile the regex */ - recomp_result = slapd_re_comp(dp->regular_expression); - if (recomp_result) { - LDAPDebug( LDAP_DEBUG_ANY, "sasl_map_check : re_comp failed for expression (%s)\n", dp->regular_expression, 0, 0 ); + /* Compiles the regex */ + re = slapi_re_comp(dp->regular_expression, &recomp_result); + if (NULL == re) { + LDAPDebug( LDAP_DEBUG_ANY, + "sasl_map_check: slapi_re_comp failed for expression (%s): %s\n", + dp->regular_expression, recomp_result?recomp_result:"unknown", 0 ); } else { - matched = slapd_re_exec(sasl_user_and_realm, -1 /* no timelimit */); - LDAPDebug( LDAP_DEBUG_TRACE, "regex: %s, id: %s, %s\n", dp->regular_expression, sasl_user_and_realm, matched ? "matched" : "didn't match" ); + /* Matches the compiled regex against sasl_user_and_realm */ + matched = slapi_re_exec(re, sasl_user_and_realm, -1 /* no timelimit */); + LDAPDebug( LDAP_DEBUG_TRACE, "regex: %s, id: %s, %s\n", + dp->regular_expression, sasl_user_and_realm, + matched ? "matched" : "didn't match" ); } if (matched) { if (matched == 1) { char escape_base[BUFSIZ]; char escape_filt[BUFSIZ]; + int ldap_search_base_len, ldap_search_filter_len; + int rc = 0; + /* Allocate buffers for the returned strings */ - /* We already computed this, so we could pass it in to speed up a little */ + /* We already computed this, so we could pass it in to speed up + * a little */ size_t userrealmlen = strlen(sasl_user_and_realm); /* These lengths could be precomputed and stored in the dp */ - *ldap_search_base = (char *) slapi_ch_malloc(userrealmlen + strlen(dp->template_base_dn) + 1); - *ldap_search_filter = (char *) slapi_ch_malloc(userrealmlen + strlen(dp->template_search_filter) + 1); - slapd_re_subs(dp->template_base_dn,*ldap_search_base); - slapd_re_subs(dp->template_search_filter,*ldap_search_filter); - /* these values are internal regex representations with lots of - unprintable control chars - escape for logging */ - LDAPDebug( LDAP_DEBUG_TRACE, "mapped base dn: %s, filter: %s\n", - escape_string( *ldap_search_base, escape_base ), - escape_string( *ldap_search_filter, escape_filt ), 0 ); - ret = 1; + ldap_search_base_len = + userrealmlen + strlen(dp->template_base_dn) + 1; + ldap_search_filter_len = + userrealmlen + strlen(dp->template_search_filter) + 1; + *ldap_search_base = (char *)slapi_ch_malloc(ldap_search_base_len); + *ldap_search_filter = + (char *)slapi_ch_malloc(ldap_search_filter_len); + /* Substitutes '&' and/or "\#" in template_base_dn */ + rc = slapi_re_subs(re, sasl_user_and_realm, dp->template_base_dn, + ldap_search_base, ldap_search_base_len); + if (0 != rc) { + LDAPDebug( LDAP_DEBUG_ANY, + "sasl_map_check: slapi_re_subs failed: " + "subject: %s, subst str: %s (%d)\n", + sasl_user_and_realm, dp->template_base_dn, rc); + } else { + /* Substitutes '&' and/or "\#" in template_search_filter */ + rc = slapi_re_subs(re, sasl_user_and_realm, + dp->template_search_filter, ldap_search_filter, + ldap_search_filter_len); + if (0 != rc) { + LDAPDebug( LDAP_DEBUG_ANY, + "sasl_map_check: slapi_re_subs failed: " + "subject: %s, subst str: %s (%d)\n", + sasl_user_and_realm, dp->template_search_filter, rc); + } else { + /* these values are internal regex representations with + * lots of unprintable control chars - escape for logging */ + LDAPDebug( LDAP_DEBUG_TRACE, + "mapped base dn: %s, filter: %s\n", + escape_string( *ldap_search_base, escape_base ), + escape_string( *ldap_search_filter, escape_filt ), 0 ); + ret = 1; + } + } } else { - LDAPDebug( LDAP_DEBUG_ANY, "sasl_map_check : re_exec failed\n", 0, 0, 0 ); + LDAPDebug( LDAP_DEBUG_ANY, + "sasl_map_check: slapi_re_exec failed: " + "regex: %s, subject: %s (%d)\n", + dp->regular_expression, sasl_user_and_realm, matched); } + slapi_re_free(re); } - slapd_re_unlock(); LDAPDebug( LDAP_DEBUG_TRACE, "<- sasl_map_check\n", 0, 0, 0 ); return ret; } diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index 3bcadde8..f0d21910 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -169,6 +169,9 @@ typedef struct symbol_t { #include "csngen.h" #include "uuid.h" +/* Perl Compatible Regular Expression */ +#include <pcre.h> + #if defined(OS_solaris) # include <thread.h> # define GET_THREAD_ID() thr_self() @@ -181,7 +184,6 @@ typedef struct symbol_t { # endif #endif - /* * XXXmcs: these are defined by ldap.h or ldap-extension.h, * but only in a newer release than we use with DS today. @@ -216,6 +218,7 @@ typedef void (*VFP0)(); #define LDAPI_INTERNAL 1 #include "slapi-private.h" #include "pw.h" + /* * call the appropriate signal() function. */ @@ -1544,8 +1547,6 @@ typedef int (*value_compare_fn_type)(const struct berval *,const struct berval * /* Definition for plugin syntax validate routine */ typedef int (*value_validate_fn_type)(const struct berval *); -#include "pw.h" - #include "proto-slap.h" LDAPMod** entry2mods(Slapi_Entry *, LDAPMod **, int *, int); diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 0ae909fd..b5e3441a 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -3352,6 +3352,54 @@ typedef struct slapi_plugindesc { #define SLAPI_IS_MOD_DELETE(x) (((x) & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) #define SLAPI_IS_MOD_REPLACE(x) (((x) & ~LDAP_MOD_BVALUES) == LDAP_MOD_REPLACE) +/* regex.c */ +typedef struct slapi_regex_handle Slapi_Regex; + +/** + * Compiles a regular expression pattern. A thin wrapper of pcre_compile. + * + * \param pat Pattern to be compiled. + * \param error The error string is set if the compile fails. + * \return This function returns a pointer to the regex handler which stores + * the compiled pattern. NULL if the compile fails. + * \warning The regex handler should be released by slapi_re_free(). + */ +Slapi_Regex *slapi_re_comp( char *pat, char **error ); +/** + * Matches a compiled regular expression pattern against a given string. + * A thin wrapper of pcre_exec. + * + * \param re_handle The regex handler returned from slapi_re_comp. + * \param subject A string to be checked against the compiled pattern. + * \param time_up If the current time is larger than the value, this function + * returns immediately. (-1) means no time limit. + * \return This function returns 0 if the string did not match. + * \return This function returns 1 if the string matched. + * \return This function returns other values if any error occurred. + * \warning The regex handler should be released by slapi_re_free(). + */ +int slapi_re_exec( Slapi_Regex *re_handle, char *subject, time_t time_up ); +/** + * Substitutes '&' or '\#' in the param src with the matched string. + * + * \param re_handle The regex handler returned from slapi_re_comp. + * \param subject A string checked against the compiled pattern. + * \param src A given string which could contain the substitution symbols. + * \param dst A pointer pointing to the memory which stores the output string. + * \param dstlen Size of the memory dst. + * \return This function returns 1 if the substitution was successful. + * \return This function returns 0 if the substitution failed. + * \warning The regex handler should be released by slapi_re_free(). + */ +int slapi_re_subs( Slapi_Regex *re_handle, char *subject, char *src, char **dst, unsigned long dstlen ); +/** + * Releases the regex handler which was returned from slapi_re_comp. + * + * \param re_handle The regex handler to be released. + * \return nothing + */ +void slapi_re_free(Slapi_Regex *re_handle); + #ifdef __cplusplus } #endif diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h index 23baf296..ab3430a4 100644 --- a/ldap/servers/slapd/slapi-private.h +++ b/ldap/servers/slapd/slapi-private.h @@ -1173,13 +1173,6 @@ typedef char*(*CFP)(); void bervalarray_add_berval_fast(struct berval ***vals, const struct berval *addval, int nvals, int *maxvals); -int slapd_re_exec( char *lp, time_t time_up ); -char *slapd_re_comp( char *pat ); -int slapd_re_subs( char *src, char* dst ); -void slapd_re_lock( void ); -int slapd_re_unlock( void ); -int slapd_re_init( void ); - /* this is the root configuration entry beneath which all plugin configuration entries will be found */ diff --git a/ldap/servers/slapd/slapi_counter_sunos_sparcv9.S b/ldap/servers/slapd/slapi_counter_sunos_sparcv9.S index 34dff541..04af8aa3 100644 --- a/ldap/servers/slapd/slapi_counter_sunos_sparcv9.S +++ b/ldap/servers/slapd/slapi_counter_sunos_sparcv9.S @@ -45,6 +45,7 @@ ! END COPYRIGHT BLOCK ! +#define _ASM 1 /* force to set an assembler code macro _ASM */ #include <sys/asm_linkage.h> ! ====================================================================== diff --git a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in index 00bd6541..e500abec 100755 --- a/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in +++ b/ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl.in @@ -719,12 +719,12 @@ for ($x= 0; $x < $Number_To_Generate; $x++) { if ($PrintOrgChartDat) { $managerCn = $managers[int rand @managers]{"dn"}; } else { - $managerCn = $managers[int rand @managers]{"givenname"} . " " . + $managerCn = "cn=" . $managers[int rand @managers]{"givenname"} . " " . $managers[int rand @managers]{"sn"}; } ($junk, $junk, $secretary_cn) = &MakeRandomName; - $manager = "manager: $managerCn " . "\n"; - $secretary = "secretary: $secretary_cn" . "\n"; + $manager = "manager: " . $managerCn . "\n"; + $secretary = "secretary: cn=" . $secretary_cn . "\n"; $roomNumber = "roomNumber: " . (int rand 10000) . "\n"; $userPassword = "$uid\n"; } @@ -931,9 +931,9 @@ sub PrintManagers { $pager = "pager: " . &MakeRandomTelephone . "\n"; ($junk, $junk, $secretary_cn) = &MakeRandomName; if ("" ne $managerCn) { - $manager = "manager: $managerCn\n"; + $manager = "manager: cn=" . $managerCn . "\n"; } - $secretary = "secretary: $secretary_cn" . "\n"; + $secretary = "secretary: cn=" . $secretary_cn . "\n"; $roomNumber = "roomNumber: " . (int rand 10000) . "\n"; $userPassword = "$uid\n"; } |