From: Kurt Zeilenga Date: Mon, 29 Dec 2003 19:10:37 +0000 (+0000) Subject: (Partial) Sync with HEAD X-Git-Tag: OPENLDAP_REL_ENG_2_2_4~8 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=73af07e062025e294345278b9dd6735bd46677da;p=openldap (Partial) Sync with HEAD --- diff --git a/doc/man/man5/slapd-bdb.5 b/doc/man/man5/slapd-bdb.5 index d24bd0cff4..4342574c7f 100644 --- a/doc/man/man5/slapd-bdb.5 +++ b/doc/man/man5/slapd-bdb.5 @@ -133,12 +133,19 @@ region that will house the environment. .TP .B sessionlog Specify a session log store for the syncrepl replication provider -site which contains information on the entries that have been scoped -out of the content of the replication session identified by {{EX:}}. -The number of entries in the session log store is limited -by {{EX:}}. Excessive entries are removed from the store -in the FIFO order. Both {{EX:}} and {{EX:}} are -non-negative integers. {{EX:}} has no more than three digits. +server. The session log store contains information on the entries that +have been scoped out of the provider replication content identified by +.B . +The number of entries in the session log store is limited by +.B . +Excessive entries are removed from the store in the FIFO order. +Both +.B +and +.B +are non-negative integers. +.B +has no more than three decimal digits. Refer to the "OpenLDAP Administrator's Guide" for detailed information on setting up a replicated slapd directory service using the syncrepl replication engine and the session log store. diff --git a/doc/man/man5/slapd-meta.5 b/doc/man/man5/slapd-meta.5 index cef94103b0..d4bfeb74f9 100644 --- a/doc/man/man5/slapd-meta.5 +++ b/doc/man/man5/slapd-meta.5 @@ -332,8 +332,8 @@ server will possibly enforce additional restrictions to "foo". A string is rewritten according to a set of rules, called a `rewrite context'. The rules are based on Regular Expressions (POSIX regex) with -substring matching; extensions are planned to allow basic variable -substitution and map resolution of substrings. +substring matching; basic variable substitution and map resolution +of substrings is allowed by specific mechanisms detailed in the following. The behavior of pattern matching/substitution can be altered by a set of flags. .LP @@ -341,14 +341,17 @@ The underlying concept is to build a lightweight rewrite module for the slapd server (initially dedicated to the LDAP backend). .SH Passes An incoming string is matched agains a set of rules. -Rules are made of a match pattern, a substitution pattern and a set of -actions. +Rules are made of a regex match pattern, a substitution pattern +and a set of actions, described by a set of flags. In case of match a string rewriting is performed according to the substitution pattern that allows to refer to substrings matched in the incoming string. The actions, if any, are finally performed. The substitution pattern allows map resolution of substrings. A map is a generic object that maps a substitution pattern to a value. +The flags are divided in "Pattern matching Flags" and "Action Flags"; +the former alter the regex match pattern behaviorm while the latter +alter the action that is taken after substitution. .SH "Pattern Matching Flags" .TP .B `C' @@ -356,31 +359,58 @@ honors case in matching (default is case insensitive) .TP .B `R' use POSIX Basic Regular Expressions (default is Extended) +.TP +.B `M{n}' +allow no more than +.B n +recursive passes for a specific rule; does not alter the max total count +of passes, so it can only enforce a stricter limit for a specific rule. .SH "Action Flags" .TP .B `:' apply the rule once only (default is recursive) .TP .B `@' -stop applying rules in case of match. +stop applying rules in case of match; the current rule is still applied +recursively; combine with `:' to apply the current rule only once +and then stop. .TP .B `#' stop current operation if the rule matches, and issue an `unwilling to perform' error. .TP .B `G{n}' -jump n rules back and forth (watch for loops!). +jump +.B n +rules back and forth (watch for loops!). Note that `G{1}' is implicit in every rule. .TP .B `I' ignores errors in rule; this means, in case of error, e.g. issued by a map, the error is treated as a missed match. The `unwilling to perform' is not overridden. -.LP -The ordering of the flags is significant. +.TP +.B `U{n}' +uses +.B +n +as return code if the rule matches; the flag does not alter the recursive +behavior of the rule, so, to have it performed only once, it must be used +in combination with `:', e.g. +.B `:U{16}' +returns the value `16' after exactly one execution of the rule, if the +pattern matches. +As a consequence, its behavior is equivalent to `@', with the return +code set to +.BR n ; +or, in other words, `@' is equivalent to `U{0}'. +By convention, the freely available codes are above 16 included; +the others are reserved. +.LP +The ordering of the flags can be significant. For instance: `IG{2}' means ignore errors and jump two lines ahead both in case of match and in case of error, while `G{2}I' means ignore -errors, but jump thwo lines ahead only in case of match. +errors, but jump two lines ahead only in case of match. .LP More flags (mainly Action Flags) will be added as needed. .SH "Pattern matching:" @@ -527,8 +557,8 @@ A context may aliase another one. In this case the alias context contains no rule, and any reference to it will result in accessing the aliased one. .TP -.B rewriteRule "" "" "[ ]" -Determines how a tring can be rewritten if a pattern is matched. +.B rewriteRule "" "" "[ ]" +Determines how a string can be rewritten if a pattern is matched. Examples are reported below. .SH "Additional configuration syntax:" .TP @@ -541,9 +571,16 @@ The map is referenced inside the substitution pattern of a rule. Sets a value with global scope, that can be dereferenced by the command `%{$paramName}'. .TP -.B rewriteMaxPasses +.B rewriteMaxPasses [] Sets the maximum number of total rewriting passes that can be performed in a single rewrite operation (to avoid loops). +A safe default is set to 100; note that reaching this limit is still +treated as a success; recursive invocation of rules is simply +interrupted. +The count applies to the rewriting operation as a whole, not +to any single rule; an optional per-rule limit can be set. +This limit is overridden by setting specific per-rule limits +with the `M{n}' flag. .SH "Configuration examples:" .nf # set to `off' to disable rewriting @@ -616,7 +653,7 @@ rewriteMap ldap attr2dn "ldap://host/dc=my,dc=org?dn?sub" # regular DNs, because the definition of a bindDn # rewrite context overrides the default definition. rewriteContext bindDn -rewriteRule "^mail=[^,]+@[^,]+$" "%{attr2dn(%0)}" "@I" +rewriteRule "^mail=[^,]+@[^,]+$" "%{attr2dn(%0)}" ":@I" # This is a rather sophisticated example. It massages a # search filter in case who performs the search has @@ -645,7 +682,7 @@ rewriteRule "(.*\e\e()uid=([a-z0-9_]+)(\e\e).*)" "%{**binddn}<>%{&prefix(%1)}%{&arg(%2)}%{&suffix(%3)}" ":I" rewriteRule "[^,]+,ou=admin,dc=home,dc=net" - "%{*prefix}|(uid=%{*arg})(cn=%{*arg})%{*suffix}" "@I" + "%{*prefix}|(uid=%{*arg})(cn=%{*arg})%{*suffix}" ":@I" rewriteRule ".*<>" "%{*prefix}uid=%{*arg}%{*suffix}" ":" # This example shows how to strip unwanted DN-valued @@ -655,7 +692,7 @@ rewriteRule ".*<>" "%{*prefix}uid=%{*arg}%{*suffix}" ":" # The second rule matches everything else and causes # the value to be rejected. rewriteContext searchResult -rewriteRule ".*,ou=People,dc=example,dc=com" "%0" "@" +rewriteRule ".*,ou=People,dc=example,dc=com" "%0" ":@" rewriteRule ".*" "" "#" .fi .SH "LDAP Proxy resolution (a possible evolution of slapd\-ldap(5)):" @@ -666,16 +703,16 @@ E.g.: .LP .nf rewriteRule '^cn=root,.*' '%0' 'G{3}' - rewriteRule '^cn=[a-l].*' 'ldap://ldap1.my.org/%0' '@' - rewriteRule '^cn=[m-z].*' 'ldap://ldap2.my.org/%0' '@' - rewriteRule '.*' 'ldap://ldap3.my.org/%0' '@' + rewriteRule '^cn=[a-l].*' 'ldap://ldap1.my.org/%0' ':@' + rewriteRule '^cn=[m-z].*' 'ldap://ldap2.my.org/%0' ':@' + rewriteRule '.*' 'ldap://ldap3.my.org/%0' ':@' .fi .LP (Rule 1 is simply there to illustrate the `G{n}' action; it could have been written: .LP .nf - rewriteRule '^cn=root,.*' 'ldap://ldap3.my.org/%0' '@' + rewriteRule '^cn=root,.*' 'ldap://ldap3.my.org/%0' ':@' .fi .LP with the advantage of saving one rewrite pass ...) diff --git a/doc/man/man5/slapd.access.5 b/doc/man/man5/slapd.access.5 index 9b49572d22..3d0ba4c2e6 100644 --- a/doc/man/man5/slapd.access.5 +++ b/doc/man/man5/slapd.access.5 @@ -91,11 +91,15 @@ or .B exact (an alias of .BR base ) -indicates the entry whose DN is equal to the pattern. +indicates the entry whose DN is equal to the pattern; .B one +(synonym of +.BR onelevel ) indicates all the entries immediately below the .BR pattern , -.B subtree +.B sub +(synonym of +.BR subtree ) indicates all entries in the subtree at the pattern, .B children indicates all the entries below (subordinate to) the pattern. @@ -370,7 +374,7 @@ Its component are defined as .LP .nf ::= none|auth|compare|search|read|write - ::= {=|+|-}{w|r|s|c|x}+ + ::= {=|+|-}{w|r|s|c|x|0}+ .fi .LP The modifier @@ -434,7 +438,9 @@ for search, for compare, and .B x for authentication. -More than one privilege can be added in one statement. +More than one of the above privileges can be added in one statement. +.B 0 +indicates no privileges and is used only by itself (e.g., +0). .LP The optional field .B diff --git a/doc/man/man8/slapadd.8 b/doc/man/man8/slapadd.8 index 6bc17bac58..a71696faaa 100644 --- a/doc/man/man8/slapadd.8 +++ b/doc/man/man8/slapadd.8 @@ -9,9 +9,13 @@ slapadd \- Add entries to a SLAPD database .B [\-v] .B [\-c] .B [\-u] +.B [\-p] +.B [\-r] +.B [\-w] .B [\-d level] .B [\-b suffix] .B [\-n dbnum] +.B [\-i rid1,rid2,...] .B [\-f slapd.conf] .B [\-l ldif-file] .B @@ -47,6 +51,26 @@ enable continue (ignore errors) mode. .B \-u enable dry-run (don't write to backend) mode. .TP +.BI \-p +If the LDIF input represents a syncrepl consumer replica, +promote it to the syncrepl provider's content after adding +the entries. +.TP +.BI \-r +If the LDIF input represents a syncrepl provider replica, +demote it to the syncrepl consumer replica after adding +the entries. +.TP +.BI \-w +When used with either +.B \-p +or +.B \-r, +rebuild the new syncrepl +information from the contents of the added entries. +The syncrepl information contained in the LDIF input +file is ignored. +.TP .BI \-d " level" enable debugging messages as defined by the specified .IR level . @@ -66,6 +90,11 @@ cannot be used in conjunction with the .B \-b option. .TP +.BI \-i " rid1,rid2,..." +Specify the replication ids for one or more syncrepl consumer +replicas contained in the LDIF input. If omitted, 0 is used +as the replication id. +.TP .BI \-f " slapd.conf" specify an alternative .BR slapd.conf (5) diff --git a/doc/man/man8/slapcat.8 b/doc/man/man8/slapcat.8 index e53faf497c..ae9e561963 100644 --- a/doc/man/man8/slapcat.8 +++ b/doc/man/man8/slapcat.8 @@ -8,6 +8,8 @@ slapcat \- SLAPD database to LDIF utility .B SBINDIR/slapcat .B [\-v] .B [\-c] +.B [\-k] +.B [\-m] .B [\-d level] .B [\-b suffix] .B [\-n dbnum] @@ -36,13 +38,23 @@ without first being reordered. .SH OPTIONS .TP .B \-v -enable verbose mode. +Enable verbose mode. .TP .B \-c -enable continue (ignore errors) mode. +Enable continue (ignore errors) mode. +.TP +.B \-k +Include +.B syncConsumerSubentry +of the syncrepl consumer in the generated LDIF output. +.TP +.B \-m +Include +.B syncProviderSubentry +of the syncrepl provider in the generated LDIF output. .TP .BI \-d " level" -enable debugging messages as defined by the specified +Enable debugging messages as defined by the specified .IR level . .TP .BI \-b " suffix" @@ -69,7 +81,7 @@ or option is given. .TP .BI \-f " slapd.conf" -specify an alternative +Specify an alternative .BR slapd.conf (5) file. .TP diff --git a/doc/man/man8/slapd.8 b/doc/man/man8/slapd.8 index 38cfc4b977..2d5d8585b0 100644 --- a/doc/man/man8/slapd.8 +++ b/doc/man/man8/slapd.8 @@ -13,6 +13,7 @@ slapd \- Stand-alone LDAP Daemon .B [\-n service\-name] [\-s syslog\-level] [\-l syslog\-local\-user] .B [\-r directory] .B [\-u user] [\-g group] [\-t] +.B [\-c cookie] .B .SH DESCRIPTION .LP @@ -172,7 +173,7 @@ will read the configuration file (the default if none is given with the or database. .TP .BI \-c " cookie" -This option provides a cookie for a syncrepl replication consumer. +This option provides a cookie for the syncrepl replication consumer. The cookie is a comma separated list of name=value pairs. Currently supported syncrepl cookie fields are .B csn, @@ -180,20 +181,18 @@ Currently supported syncrepl cookie fields are and .B rid. .B csn -is the commit sequence number of the master content at the provider site -and represents the state of the content to which the replica content -was synchronized most recently. +is the commit sequence number received by a previous synchronization +and represents the state of the consumer replica content which the +syncrepl engine will synchronize to the current provider content. .B sid -is the identity of the session which this replication thread belongs to. -The replication provider site may maintain a session history store -for each replication session to reduce synchronization traffic. +is the identity of the per-scope session log with which the +provider server can process this syncrepl request to reduce +synchronization traffic. .B rid -identifies a replication thread within a replication consumer site -and is used to find the replication thread specification of +identifies a replication thread within the consumer server +and is used to find the syncrepl specification in .BR slapd.conf (5) -having the same -.B rid -value as the cookie. +having the matching replication identifier in its definition. .SH EXAMPLES To start .I slapd diff --git a/include/ldap_defaults.h b/include/ldap_defaults.h index 87f497c4a0..510e37b7f1 100644 --- a/include/ldap_defaults.h +++ b/include/ldap_defaults.h @@ -39,35 +39,7 @@ #define LDAP_ENV_PREFIX "LDAP" /* default ldapi:// socket */ -#define LDAPI_SOCK LDAP_RUNDIR LDAP_DIRSEP "ldapi" - -/* - * MAIL500 MAILER DEFINITIONS - */ - /* max number of ambiguous matches reported */ -#define MAIL500_MAXAMBIGUOUS 10 - /* max subscribers allowed (size limit when searching for them ) */ -#define MAIL500_MAXGROUPMEMBERS LDAP_NO_LIMIT - /* timeout for all searches */ -#define MAIL500_TIMEOUT 180 - /* sendmail location - mail500 needs to exec this */ -#define MAIL500_SENDMAIL LDAP_SENDMAIL - -/* - * UD DEFINITIONS - */ - /* default config file locations */ -#define FILTERFILE LDAP_SYSCONFDIR LDAP_DIRSEP "ldapfilter.conf" - /* ud configuration file */ -#define UD_CONFIG_FILE LDAP_SYSCONFDIR LDAP_DIRSEP "ud.conf" - /* default editor */ -#define UD_DEFAULT_EDITOR LDAP_EDITOR - /* default bbasename of user config file */ -#define UD_USER_CONFIG_FILE ".udrc" - /* default base where groups are created */ -#define UD_WHERE_GROUPS_ARE_CREATED "" - /* default base below which all groups live */ -#define UD_WHERE_ALL_GROUPS_LIVE "" +#define LDAPI_SOCK LDAP_RUNDIR LDAP_DIRSEP "run" LDAP_DIRSEP "ldapi" /* * SLAPD DEFINITIONS diff --git a/include/rewrite.h b/include/rewrite.h index fdf7c1f4df..9178c89ef6 100644 --- a/include/rewrite.h +++ b/include/rewrite.h @@ -1,26 +1,23 @@ -/****************************************************************************** +/* $OpenLDAP$ + */ +/* This work is part of OpenLDAP Software . * - * Copyright (C) 2000 Pierangelo Masarati, + * Copyright 2000-2003 The OpenLDAP Foundation. + * Portions Copyright 2000-2003 Pierangelo Masarati. * All rights reserved. * - * Permission is granted to anyone to use this software for any purpose - * on any computer system, and to alter it and redistribute it, subject - * to the following restrictions: - * - * 1. The author is not responsible for the consequences of use of this - * software, no matter how awful, even if they arise from flaws in it. - * - * 2. The origin of this software must not be misrepresented, either by - * explicit claim or by omission. Since few users ever read sources, - * credits should appear in the documentation. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. * - * 3. Altered versions must be plainly marked as such, and must not be - * misrepresented as being the original software. Since few users - * ever read sources, credits should appear in the documentation. - * - * 4. This notice may not be removed or altered. - * - ******************************************************************************/ + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* ACKNOWLEDGEMENT: + * This work was initially developed by Pierangelo Masarati for + * inclusion in OpenLDAP Software. + */ #ifndef REWRITE_H #define REWRITE_H @@ -72,7 +69,33 @@ #define REWRITE_REGEXEC_OK 0x0000 #define REWRITE_REGEXEC_ERR 0x0001 #define REWRITE_REGEXEC_STOP 0x0002 -#define REWRITE_REGEXEC_UNWILLING 0x0004 +#define REWRITE_REGEXEC_UNWILLING 0x0003 +#define REWRITE_REGEXEC_USER 0x0004 /* and above ... */ + +/* + * Rewrite variable flags + * REWRITE_VAR_INSERT insert mode (default) when adding + * a variable; if not set during value + * update, the variable is not inserted + * if not present + * REWRITE_VAR_UPDATE update mode (default) when updating + * a variable; if not set during insert, + * the value is not updated if the + * variable already exists + * REWRITE_VAR_COPY_NAME copy the variable name; if not set, + * the name is not copied; be sure the + * referenced string is available for + * the entire life scope of the variable. + * REWRITE_VAR_COPY_VALUE copy the variable value; if not set, + * the value is not copied; be sure the + * referenced string is available for + * the entire life scope of the variable. + */ +#define REWRITE_VAR_NONE 0x0000 +#define REWRITE_VAR_INSERT 0x0001 +#define REWRITE_VAR_UPDATE 0x0002 +#define REWRITE_VAR_COPY_NAME 0x0004 +#define REWRITE_VAR_COPY_VALUE 0x0008 /* * Rewrite info @@ -177,13 +200,18 @@ rewrite_session_init( * Defines and inits a variable with session scope */ LDAP_REWRITE_F (int) -rewrite_session_var_set( +rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, - const char *value + const char *value, + int flags ); +#define rewrite_session_var_set(info, cookie, name, value) \ + rewrite_session_var_set_f((info), (cookie), (name), (value), \ + REWRITE_VAR_INSERT|REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE) + /* * Deletes a session */ diff --git a/include/slapi-plugin.h b/include/slapi-plugin.h index 551e3d2e90..a7a46a7aa7 100644 --- a/include/slapi-plugin.h +++ b/include/slapi-plugin.h @@ -14,6 +14,12 @@ * . */ +/* + * This header is used in development of SLAPI plugins for + * OpenLDAP slapd(8) and other directory servers supporting + * this interface. Your portability mileage may vary. + */ + #ifndef _SLAPI_PLUGIN_H #define _SLAPI_PLUGIN_H diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 09fa94e01e..c3687a4397 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -585,10 +585,15 @@ ldap_host_connected_to( Sockbuf *sb, const char *host ) break; } -#if 0 { char *herr; +#ifdef NI_MAXHOST char hbuf[NI_MAXHOST]; +#elif defined( MAXHOSTNAMELEN + char hbuf[MAXHOSTNAMELEN]; +#else + char hbuf[256]; +#endif hbuf[0] = 0; if (ldap_pvt_get_hname( sa, len, hbuf, sizeof(hbuf), &herr ) == 0 @@ -597,7 +602,6 @@ ldap_host_connected_to( Sockbuf *sb, const char *host ) return LDAP_STRDUP( hbuf ); } } -#endif return host ? LDAP_STRDUP( host ) : NULL; } diff --git a/libraries/librewrite/config.c b/libraries/librewrite/config.c index 9cf3ad98dc..da33b467a5 100644 --- a/libraries/librewrite/config.c +++ b/libraries/librewrite/config.c @@ -39,7 +39,7 @@ rewrite_parse_builtin_map( * lines handled are of the form: * * rewriteEngine {on|off} - * rewriteMaxPasses numPasses + * rewriteMaxPasses numPasses [numPassesPerRule] * rewriteContext contextName [alias aliasedContextName] * rewriteRule pattern substPattern [ruleFlags] * rewriteMap mapType mapName [mapArgs] @@ -103,7 +103,25 @@ rewrite_parse( fname, lineno, "" ); return -1; } + info->li_max_passes = atoi( argv[ 1 ] ); + if ( info->li_max_passes <= 0 ) { + Debug( LDAP_DEBUG_ANY, + "[%s:%d] negative or null rewriteMaxPasses'\n", + fname, lineno, 0 ); + } + + if ( argc > 2 ) { + info->li_max_passes_per_rule = atoi( argv[ 2 ] ); + if ( info->li_max_passes_per_rule <= 0 ) { + Debug( LDAP_DEBUG_ANY, + "[%s:%d] negative or null rewriteMaxPassesPerRule'\n", + fname, lineno, 0 ); + } + + } else { + info->li_max_passes_per_rule = info->li_max_passes; + } rc = REWRITE_SUCCESS; /* diff --git a/libraries/librewrite/context.c b/libraries/librewrite/context.c index 281fbb4550..bfa1b77d17 100644 --- a/libraries/librewrite/context.c +++ b/libraries/librewrite/context.c @@ -357,6 +357,15 @@ rewrite_context_apply( goto rc_end_of_context; } break; + + /* + * This ends the rewrite context + * and returns a user-defined + * error code + */ + case REWRITE_ACTION_USER: + return_code = ((int *)action->la_args)[ 0 ]; + goto rc_end_of_context; default: /* ... */ @@ -385,10 +394,17 @@ rewrite_context_apply( * This will instruct the server to return * an `unwilling to perform' error message */ - case REWRITE_REGEXEC_UNWILLING: + case REWRITE_REGEXEC_UNWILLING: return_code = REWRITE_REGEXEC_UNWILLING; goto rc_end_of_context; + /* + * A user-defined error code has propagated ... + */ + default: + assert( rc >= REWRITE_REGEXEC_USER ); + goto rc_end_of_context; + } rc_continue:; /* sent here by actions that require to continue */ diff --git a/libraries/librewrite/info.c b/libraries/librewrite/info.c index ef95f5da84..faa2424c3f 100644 --- a/libraries/librewrite/info.c +++ b/libraries/librewrite/info.c @@ -67,6 +67,7 @@ rewrite_info_init( info->li_state = REWRITE_DEFAULT; info->li_max_passes = REWRITE_MAX_PASSES; + info->li_max_passes_per_rule = REWRITE_MAX_PASSES; info->li_rewrite_mode = mode; /* @@ -259,11 +260,13 @@ rewrite_session( */ case REWRITE_REGEXEC_UNWILLING: case REWRITE_REGEXEC_ERR: - default: if ( *result != NULL ) { free( *result ); *result = NULL; } + + default: + break; } rc_return:; diff --git a/libraries/librewrite/rewrite-int.h b/libraries/librewrite/rewrite-int.h index 3f14b0c160..bfdbff1220 100644 --- a/libraries/librewrite/rewrite-int.h +++ b/libraries/librewrite/rewrite-int.h @@ -71,6 +71,8 @@ #define REWRITE_FLAG_STOP '@' #define REWRITE_FLAG_UNWILLING '#' #define REWRITE_FLAG_GOTO 'G' /* requires an arg */ +#define REWRITE_FLAG_USER 'U' /* requires an arg */ +#define REWRITE_FLAG_MAX_PASSES 'M' /* requires an arg */ #define REWRITE_FLAG_IGNORE_ERR 'I' /* @@ -97,6 +99,7 @@ struct rewrite_action { #define REWRITE_ACTION_UNWILLING 0x0002 #define REWRITE_ACTION_GOTO 0x0003 #define REWRITE_ACTION_IGNORE_ERR 0x0004 +#define REWRITE_ACTION_USER 0x0005 int la_type; void *la_args; }; @@ -217,6 +220,7 @@ struct rewrite_rule { #define REWRITE_RECURSE 0x0001 #define REWRITE_EXEC_ONCE 0x0002 int lr_mode; + int lr_max_passes; struct rewrite_action *lr_action; }; @@ -248,6 +252,7 @@ struct rewrite_session { */ struct rewrite_var { char *lv_name; + int lv_flags; struct berval lv_value; }; @@ -301,6 +306,7 @@ struct rewrite_info { */ #define REWRITE_MAXPASSES 100 int li_max_passes; + int li_max_passes_per_rule; /* * Behavior in case a NULL or non-existent context is required @@ -459,11 +465,12 @@ rewrite_session_find( * Defines and inits a variable with session scope */ LDAP_REWRITE_F (int) -rewrite_session_var_set( +rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, - const char *value + const char *value, + int flags ); /* @@ -508,27 +515,46 @@ rewrite_var_find( const char *name ); +/* + * Replaces the value of a variable + */ +LDAP_REWRITE_F (int) +rewrite_var_replace( + struct rewrite_var *var, + const char *value, + int flags +); + /* * Inserts a newly created var */ LDAP_REWRITE_F (struct rewrite_var *) -rewrite_var_insert( +rewrite_var_insert_f( Avlnode **tree, const char *name, - const char *value + const char *value, + int flags ); +#define rewrite_var_insert(tree, name, value) \ + rewrite_var_insert_f((tree), (name), (value), \ + REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE) + /* * Sets/inserts a var */ LDAP_REWRITE_F (struct rewrite_var *) -rewrite_var_set( +rewrite_var_set_f( Avlnode **tree, const char *name, const char *value, - int insert + int flags ); +#define rewrite_var_set(tree, name, value, insert) \ + rewrite_var_set_f((tree), (name), (value), \ + REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0)) + /* * Deletes a var tree */ diff --git a/libraries/librewrite/rewrite.c b/libraries/librewrite/rewrite.c index 927e1e382c..40d83d8a74 100644 --- a/libraries/librewrite/rewrite.c +++ b/libraries/librewrite/rewrite.c @@ -62,6 +62,8 @@ apply( rewriteContext != NULL; rewriteContext = sep, sep ? sep = strchr( rewriteContext, ',' ) : NULL ) { + char *errmsg = ""; + if ( sep != NULL ) { sep[ 0 ] = '\0'; sep++; @@ -70,8 +72,35 @@ apply( rc = rewrite_session( info, rewriteContext, string, cookie, &result ); - fprintf( stdout, "%s -> %s\n", string, - ( result ? result : "unwilling to perform" ) ); + switch ( rc ) { + case REWRITE_REGEXEC_OK: + errmsg = "ok"; + break; + + case REWRITE_REGEXEC_ERR: + errmsg = "error"; + break; + + case REWRITE_REGEXEC_STOP: + errmsg = "stop"; + break; + + case REWRITE_REGEXEC_UNWILLING: + errmsg = "unwilling to perform"; + break; + + default: + if (rc >= REWRITE_REGEXEC_USER) { + errmsg = "user-defined"; + } else { + errmsg = "unknown"; + } + break; + } + + fprintf( stdout, "%s -> %s [%d:%s]\n", string, + ( result ? result : "(null)" ), + rc, errmsg ); if ( result == NULL ) { break; } diff --git a/libraries/librewrite/rule.c b/libraries/librewrite/rule.c index 60531735fe..e5a0732703 100644 --- a/libraries/librewrite/rule.c +++ b/libraries/librewrite/rule.c @@ -50,17 +50,17 @@ append_rule( */ static int append_action( - struct rewrite_action *base, + struct rewrite_action **pbase, struct rewrite_action *action ) { - struct rewrite_action *a; + struct rewrite_action **pa; - assert( base != NULL ); + assert( pbase != NULL ); assert( action != NULL ); - for ( a = base; a->la_next != NULL; a = a->la_next ); - a->la_next = action; + for ( pa = pbase; *pa != NULL; pa = &(*pa)->la_next ); + *pa = action; return REWRITE_SUCCESS; } @@ -79,7 +79,8 @@ destroy_action( /* do something */ switch ( action->la_type ) { - case REWRITE_FLAG_GOTO: { + case REWRITE_FLAG_GOTO: + case REWRITE_FLAG_USER: { int *pi = (int *)action->la_args; if ( pi ) { @@ -115,6 +116,7 @@ rewrite_rule_compile( { int flags = REWRITE_REGEX_EXTENDED | REWRITE_REGEX_ICASE; int mode = REWRITE_RECURSE; + int max_passes = info->li_max_passes_per_rule; struct rewrite_rule *rule = NULL; struct rewrite_subst *subst = NULL; @@ -188,8 +190,8 @@ rewrite_rule_compile( return REWRITE_ERR; } - mode &= ~REWRITE_RECURSE; - mode |= REWRITE_EXEC_ONCE; + //mode &= ~REWRITE_RECURSE; + //mode |= REWRITE_EXEC_ONCE; action->la_type = REWRITE_ACTION_STOP; break; @@ -208,13 +210,17 @@ rewrite_rule_compile( action->la_type = REWRITE_ACTION_UNWILLING; break; - case REWRITE_FLAG_GOTO: { /* 'G' */ + case REWRITE_FLAG_GOTO: /* 'G' */ /* * After applying rule, jump N rules */ - char buf[16], *q; - size_t l; + case REWRITE_FLAG_USER: { /* 'U' */ + /* + * After applying rule, return user-defined + * error code + */ + char *next = NULL; int *d; if ( p[ 1 ] != '{' ) { @@ -222,36 +228,66 @@ rewrite_rule_compile( return REWRITE_ERR; } - q = strchr( p + 2, '}' ); - if ( q == NULL ) { - /* XXX Need to free stuff */ - return REWRITE_ERR; - } - - l = q - p + 2; - if ( l >= sizeof( buf ) ) { + d = malloc( sizeof( int ) ); + if ( d == NULL ) { /* XXX Need to free stuff */ return REWRITE_ERR; } - AC_MEMCPY( buf, p + 2, l ); - buf[ l ] = '\0'; - d = malloc( sizeof( int ) ); - if ( d == NULL ) { + d[ 0 ] = strtol( &p[ 2 ], &next, 0 ); + if ( next == NULL || next == &p[ 2 ] || next[0] != '}' ) { /* XXX Need to free stuff */ return REWRITE_ERR; } - d[ 0 ] = atoi( buf ); action = calloc( sizeof( struct rewrite_action ), 1 ); if ( action == NULL ) { /* cleanup ... */ return REWRITE_ERR; } - action->la_type = REWRITE_ACTION_GOTO; + switch ( p[ 0 ] ) { + case REWRITE_FLAG_GOTO: + action->la_type = REWRITE_ACTION_GOTO; + break; + + case REWRITE_FLAG_USER: + action->la_type = REWRITE_ACTION_USER; + break; + + default: + assert(0); + } + action->la_args = (void *)d; - p = q; /* p is incremented by the for ... */ + p = next; /* p is incremented by the for ... */ + + break; + } + + case REWRITE_FLAG_MAX_PASSES: { /* 'U' */ + /* + * Set the number of max passes per rule + */ + char *next = NULL; + + if ( p[ 1 ] != '{' ) { + /* XXX Need to free stuff */ + return REWRITE_ERR; + } + + max_passes = strtol( &p[ 2 ], &next, 0 ); + if ( next == NULL || next == &p[ 2 ] || next[0] != '}' ) { + /* XXX Need to free stuff */ + return REWRITE_ERR; + } + + if ( max_passes < 1 ) { + /* FIXME: nonsense ... */ + max_passes = 1; + } + + p = next; /* p is incremented by the for ... */ break; } @@ -283,11 +319,7 @@ rewrite_rule_compile( * Stupid way to append to a list ... */ if ( action != NULL ) { - if ( first_action == NULL ) { - first_action = action; - } else { - append_action( first_action, action ); - } + append_action( &first_action, action ); action = NULL; } } @@ -333,6 +365,7 @@ rewrite_rule_compile( */ rule->lr_flags = flags; /* don't really need any longer ... */ rule->lr_mode = mode; + rule->lr_max_passes = max_passes; rule->lr_action = first_action; /* @@ -383,8 +416,8 @@ rewrite_rule_apply( recurse:; Debug( LDAP_DEBUG_TRACE, "==> rewrite_rule_apply" - " rule='%s' string='%s'\n", - rule->lr_pattern, string, 0 ); + " rule='%s' string='%s' [%s pass(es)]\n", + rule->lr_pattern, string, strcnt + 1 ); op->lo_num_passes++; if ( regexec( &rule->lr_regex, string, nmatch, match, 0 ) != 0 ) { @@ -414,9 +447,9 @@ recurse:; } if ( ( rule->lr_mode & REWRITE_RECURSE ) == REWRITE_RECURSE - && op->lo_num_passes <= info->li_max_passes ) { + && op->lo_num_passes < info->li_max_passes + && ++strcnt < rule->lr_max_passes ) { string = *result; - strcnt++; goto recurse; } diff --git a/libraries/librewrite/session.c b/libraries/librewrite/session.c index 3a09fb40d2..34feb4959e 100644 --- a/libraries/librewrite/session.c +++ b/libraries/librewrite/session.c @@ -185,11 +185,12 @@ rewrite_session_return( * Defines and inits a var with session scope */ int -rewrite_session_var_set( +rewrite_session_var_set_f( struct rewrite_info *info, const void *cookie, const char *name, - const char *value + const char *value, + int flags ) { struct rewrite_session *session; @@ -212,11 +213,11 @@ rewrite_session_var_set( var = rewrite_var_find( session->ls_vars, name ); if ( var != NULL ) { assert( var->lv_value.bv_val != NULL ); - free( var->lv_value.bv_val ); - var->lv_value.bv_val = strdup( value ); - var->lv_value.bv_len = strlen( value ); + + (void)rewrite_var_replace( var, value, flags ); + } else { - var = rewrite_var_insert( &session->ls_vars, name, value ); + var = rewrite_var_insert_f( &session->ls_vars, name, value, flags ); if ( var == NULL ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); diff --git a/libraries/librewrite/subst.c b/libraries/librewrite/subst.c index ee32dbd76f..fe055a35cc 100644 --- a/libraries/librewrite/subst.c +++ b/libraries/librewrite/subst.c @@ -27,7 +27,7 @@ struct rewrite_subst * rewrite_subst_compile( struct rewrite_info *info, - const char *result + const char *str ) { size_t subs_len; @@ -36,11 +36,16 @@ rewrite_subst_compile( struct rewrite_subst *s = NULL; - const char *begin, *p; + char *result, *begin, *p; int nsub = 0, l; assert( info != NULL ); - assert( result != NULL ); + assert( str != NULL ); + + result = strdup( str ); + if ( result == NULL ) { + return NULL; + } /* * Take care of substitution string @@ -63,8 +68,7 @@ rewrite_subst_compile( tmps = ( struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) ); if ( tmps == NULL ) { - /* FIXME: cleanup */ - return NULL; + goto cleanup; } subs = tmps; @@ -78,7 +82,7 @@ rewrite_subst_compile( subs[ nsub ].bv_len = l; subs[ nsub ].bv_val = malloc( l + 1 ); if ( subs[ nsub ].bv_val == NULL ) { - return NULL; + goto cleanup; } AC_MEMCPY( subs[ nsub ].bv_val, begin, l ); subs[ nsub ].bv_val[ l ] = '\0'; @@ -101,8 +105,7 @@ rewrite_subst_compile( tmpsm = ( struct rewrite_submatch * )realloc( submatch, sizeof( struct rewrite_submatch )*( nsub + 1 ) ); if ( tmpsm == NULL ) { - /* cleanup */ - return NULL; + goto cleanup; } submatch = tmpsm; submatch[ nsub ].ls_submatch = d; @@ -124,10 +127,9 @@ rewrite_subst_compile( REWRITE_SUBMATCH_XMAP; map = rewrite_xmap_parse( info, - p + 3, &begin ); + p + 3, (const char **)&begin ); if ( map == NULL ) { - /* cleanup */ - return NULL; + goto cleanup; } submatch[ nsub ].ls_map = map; p = begin - 1; @@ -140,10 +142,10 @@ rewrite_subst_compile( struct rewrite_map *map; struct rewrite_submatch *tmpsm; - map = rewrite_map_parse( info, p + 2, &begin ); + map = rewrite_map_parse( info, p + 2, + (const char **)&begin ); if ( map == NULL ) { - /* cleanup */ - return NULL; + goto cleanup; } p = begin - 1; @@ -153,13 +155,22 @@ rewrite_subst_compile( tmpsm = ( struct rewrite_submatch * )realloc( submatch, sizeof( struct rewrite_submatch )*( nsub + 1 ) ); if ( tmpsm == NULL ) { - /* cleanup */ - return NULL; + goto cleanup; } submatch = tmpsm; submatch[ nsub ].ls_type = REWRITE_SUBMATCH_MAP_W_ARG; submatch[ nsub ].ls_map = map; + + /* + * Escape '%' ... + */ + } else if ( p[ 1 ] == '%' ) { + AC_MEMCPY( &p[ 1 ], &p[ 2 ], strlen( &p[ 1 ] ) ); + continue; + + } else { + goto cleanup; } nsub++; @@ -174,7 +185,7 @@ rewrite_subst_compile( * XXX need to free the value subst stuff! */ free( subs ); - return NULL; + goto cleanup; } subs = tmps; l = p - begin; @@ -191,8 +202,7 @@ rewrite_subst_compile( s = calloc( sizeof( struct rewrite_subst ), 1 ); if ( s == NULL ) { - /* cleanup */ - return NULL; + goto cleanup; } s->lt_subs_len = subs_len; @@ -200,6 +210,9 @@ rewrite_subst_compile( s->lt_num_submatch = nsub; s->lt_submatch = submatch; +cleanup:; + free( result ); + return s; } @@ -321,7 +334,6 @@ rewrite_subst_apply( } if ( rc != REWRITE_SUCCESS ) { - rc = REWRITE_REGEXEC_ERR; goto cleanup; } break; @@ -372,7 +384,7 @@ rewrite_subst_apply( rc = REWRITE_ERR; break; } - + if ( rc != REWRITE_SUCCESS ) { rc = REWRITE_REGEXEC_ERR; } diff --git a/libraries/librewrite/var.c b/libraries/librewrite/var.c index 6f84697894..80bba9f182 100644 --- a/libraries/librewrite/var.c +++ b/libraries/librewrite/var.c @@ -65,6 +65,39 @@ rewrite_var_dup( return ( strcasecmp( v1->lv_name, v2->lv_name ) == 0 ? -1 : 0 ); } +/* + * Frees a var + */ +static void +rewrite_var_free( + void *v_var +) +{ + struct rewrite_var *var = v_var; + assert( var != NULL ); + + assert( var->lv_name != NULL ); + assert( var->lv_value.bv_val != NULL ); + + if ( var->lv_flags & REWRITE_VAR_COPY_NAME ) + free( var->lv_name ); + if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) + free( var->lv_value.bv_val ); + free( var ); +} + +/* + * Deletes a var tree + */ +int +rewrite_var_delete( + Avlnode *tree +) +{ + avl_free( tree, rewrite_var_free ); + return REWRITE_SUCCESS; +} + /* * Finds a var */ @@ -83,51 +116,112 @@ rewrite_var_find( ( caddr_t )&var, rewrite_var_cmp ); } +int +rewrite_var_replace( + struct rewrite_var *var, + const char *value, + int flags +) +{ + ber_len_t len = strlen( value ); + + if ( var->lv_flags & REWRITE_VAR_COPY_VALUE ) { + if ( flags & REWRITE_VAR_COPY_VALUE ) { + if ( len <= var->lv_value.bv_len ) { + AC_MEMCPY(var->lv_value.bv_val, value, len + 1); + + } else { + free( var->lv_value.bv_val ); + var->lv_value.bv_val = strdup( value ); + } + + } else { + free( var->lv_value.bv_val ); + var->lv_value.bv_val = (char *)value; + var->lv_flags &= ~REWRITE_VAR_COPY_VALUE; + } + + } else { + if ( flags & REWRITE_VAR_COPY_VALUE ) { + var->lv_value.bv_val = strdup( value ); + var->lv_flags |= REWRITE_VAR_COPY_VALUE; + + } else { + var->lv_value.bv_val = (char *)value; + } + } + + var->lv_value.bv_len = len; + + return 0; +} + /* * Inserts a newly created var */ struct rewrite_var * -rewrite_var_insert( +rewrite_var_insert_f( Avlnode **tree, const char *name, - const char *value + const char *value, + int flags ) { struct rewrite_var *var; - int rc; + int rc = 0; assert( tree != NULL ); assert( name != NULL ); assert( value != NULL ); + var = rewrite_var_find( *tree, name ); + if ( var != NULL ) { + if ( flags & REWRITE_VAR_UPDATE ) { + (void)rewrite_var_replace( var, value, flags ); + goto cleanup; + } + rc = -1; + goto cleanup; + } + var = calloc( sizeof( struct rewrite_var ), 1 ); if ( var == NULL ) { return NULL; } + memset( var, 0, sizeof( struct rewrite_var ) ); - var->lv_name = strdup( name ); - if ( var->lv_name == NULL ) { - rc = -1; - goto cleanup; + + if ( flags & REWRITE_VAR_COPY_NAME ) { + var->lv_name = strdup( name ); + if ( var->lv_name == NULL ) { + rc = -1; + goto cleanup; + } + var->lv_flags |= REWRITE_VAR_COPY_NAME; + + } else { + var->lv_name = (char *)name; } - var->lv_value.bv_val = strdup( value ); - if ( var->lv_value.bv_val == NULL ) { - rc = -1; - goto cleanup; + + if ( flags & REWRITE_VAR_COPY_VALUE ) { + var->lv_value.bv_val = strdup( value ); + if ( var->lv_value.bv_val == NULL ) { + rc = -1; + goto cleanup; + } + var->lv_flags |= REWRITE_VAR_COPY_VALUE; + + } else { + var->lv_value.bv_val = (char *)value; } var->lv_value.bv_len = strlen( value ); rc = avl_insert( tree, ( caddr_t )var, rewrite_var_cmp, rewrite_var_dup ); - if ( rc != 0 ) { - rc = -1; - goto cleanup; - } cleanup:; - if ( rc != 0 ) { - free( var->lv_name ); - free( var->lv_value.bv_val ); - free( var ); + if ( rc != 0 && var ) { + avl_delete( tree, ( caddr_t )var, rewrite_var_cmp ); + rewrite_var_free( var ); var = NULL; } @@ -138,11 +232,11 @@ cleanup:; * Sets/inserts a var */ struct rewrite_var * -rewrite_var_set( +rewrite_var_set_f( Avlnode **tree, const char *name, const char *value, - int insert + int flags ) { struct rewrite_var *var; @@ -153,50 +247,19 @@ rewrite_var_set( var = rewrite_var_find( *tree, name ); if ( var == NULL ) { - if ( insert ) { - return rewrite_var_insert( tree, name, value ); + if ( flags & REWRITE_VAR_INSERT ) { + return rewrite_var_insert_f( tree, name, value, flags ); + } else { return NULL; } + } else { assert( var->lv_value.bv_val != NULL ); - free( var->lv_value.bv_val ); - var->lv_value.bv_val = ( char * )value; - var->lv_value.bv_len = strlen( value ); + (void)rewrite_var_replace( var, value, flags ); } return var; } -/* - * Frees a var - */ -static void -rewrite_var_free( - void *v_var -) -{ - struct rewrite_var *var = v_var; - assert( var != NULL ); - - assert( var->lv_name != NULL ); - assert( var->lv_value.bv_val != NULL ); - - free( var->lv_name ); - free( var->lv_value.bv_val ); - free( var ); -} - -/* - * Deletes a var tree - */ -int -rewrite_var_delete( - Avlnode *tree -) -{ - avl_free( tree, rewrite_var_free ); - return REWRITE_SUCCESS; -} - diff --git a/servers/slapd/Makefile.in b/servers/slapd/Makefile.in index 7dfe72d35e..1934b6e86d 100644 --- a/servers/slapd/Makefile.in +++ b/servers/slapd/Makefile.in @@ -343,7 +343,7 @@ install-local-srv: install-slapd install-conf install-schema install-tools install-slapd: FORCE -$(MKDIR) $(DESTDIR)$(libexecdir) - -$(MKDIR) $(DESTDIR)$(localstatedir) + -$(MKDIR) $(DESTDIR)$(localstatedir)/run $(LTINSTALL) $(INSTALLFLAGS) -s -m 755 \ slapd$(EXEEXT) $(DESTDIR)$(libexecdir) @for i in $(SUBDIRS); do \ diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 57f740af98..6a56c98cf9 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -36,6 +36,10 @@ #include "sets.h" #include "lber_pvt.h" +#ifdef LDAP_SLAPI +#include "slapi/slapi.h" +#endif /* LDAPI_SLAPI */ + #define ACL_BUF_SIZE 1024 /* use most appropriate size */ /* diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 609a2b5f12..913ac99f19 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -184,7 +184,8 @@ parse_acl( a->acl_dn_style = ACL_STYLE_BASE; ber_str2bv( right, 0, 1, &a->acl_dn_pat ); - } else if ( strcasecmp( style, "one" ) == 0 ) { + } else if ( strcasecmp( style, "onelevel" ) == 0 + || strcasecmp( style, "one" ) == 0 ) { a->acl_dn_style = ACL_STYLE_ONE; ber_str2bv( right, 0, 1, &a->acl_dn_pat ); @@ -245,7 +246,8 @@ parse_acl( acl_usage(); } - } else if ( strncasecmp( left, "attr", 4 ) == 0 ) { + } else if ( strcasecmp( left, "attr" ) == 0 + || strcasecmp( left, "attrs" ) == 0 ) { a->acl_attrs = str2anlist( a->acl_attrs, right, "," ); if ( a->acl_attrs == NULL ) { @@ -401,7 +403,8 @@ parse_acl( { sty = ACL_STYLE_BASE; - } else if ( strcasecmp( style, "one" ) == 0 ) { + } else if ( strcasecmp( style, "onelevel" ) == 0 || + strcasecmp( style, "one" ) == 0 ) { sty = ACL_STYLE_ONE; } else if ( strcasecmp( style, "subtree" ) == 0 || @@ -1396,7 +1399,7 @@ acl_usage( void ) "