]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
import URI parsing fix from HEAD
authorPierangelo Masarati <ando@openldap.org>
Thu, 13 Sep 2007 21:33:55 +0000 (21:33 +0000)
committerPierangelo Masarati <ando@openldap.org>
Thu, 13 Sep 2007 21:33:55 +0000 (21:33 +0000)
doc/man/man5/slapd-meta.5
servers/slapd/back-meta/config.c

index 1e22959a654069cf23c2a3a702747eddc8f873f6..b64c9de345685db0ccddf2365dfc0d2be3c43e22 100644 (file)
@@ -8,7 +8,7 @@
 .\" and maybe manual pages for librewrite.
 .\"
 .SH NAME
-slapd-meta \- metadirectory backend
+slapd-meta \- metadirectory backend to slapd
 .SH SYNOPSIS
 ETCDIR/slapd.conf
 .SH DESCRIPTION
@@ -68,17 +68,16 @@ lastmod  off
 .fi
 .RE
 .LP
-for every
+for 
 .B ldap
 and
 .B meta
-database.
-This is because operational attributes related to entry creation and
-modification should not be proxied, as they could be mistakenly written
+databases.
+This was required because operational attributes related to entry creation 
+and modification should not be proxied, as they could be mistakenly written
 to the target server(s), generating an error.
-The current implementation automatically sets lastmod to off, so its use
-is redundant and should be omitted, because the lastmod directive will
-be deprecated in the future.
+The current implementation automatically sets lastmod to \fBoff\fP, 
+so its use is redundant and should be omitted.
 
 .SH SPECIAL CONFIGURATION DIRECTIVES
 Target configuration starts with the "uri" directive.
@@ -87,6 +86,11 @@ should be defined first for clarity, including those that are common
 to all backends.
 They are:
 
+.TP
+.B conn-ttl <time>
+This directive causes a cached connection to be dropped an recreated
+after a given ttl, regardless of being idle or not.
+
 .TP
 .B default-target none
 This directive forces the backend to reject all those operations
@@ -111,19 +115,17 @@ illustrated for the
 directive.
 
 .TP
-.B conn-ttl <time>
-This directive causes a cached connection to be dropped an recreated
-after a given ttl, regardless of being idle or not.
-
-.TP
-.B onerr {CONTINUE|stop}
+.B onerr {CONTINUE|report|stop}
 This directive allows to select the behavior in case an error is returned
 by one target during a search.
 The default, \fBcontinue\fP, consists in continuing the operation, 
 trying to return as much data as possible.
-If this statement is set to \fBstop\fP, the search is terminated as soon 
+If the value is set to \fBstop\fP, the search is terminated as soon 
 as an error is returned by one target, and the error is immediately 
 propagated to the client.
+If the value is set to \fBreport\fP, the search is continuated to the end
+but, in case at least one target returned an error code, the first
+non-success error code is returned.
 
 .TP
 .B protocol\-version {0,2,3}
@@ -143,6 +145,24 @@ This directive, when set to
 causes the authentication to the remote servers with the pseudo-root
 identity to be deferred until actually needed by subsequent operations.
 
+.TP
+.B quarantine <interval>,<num>[;<interval>,<num>[...]]
+Turns on quarantine of URIs that returned
+.IR LDAP_UNAVAILABLE ,
+so that an attempt to reconnect only occurs at given intervals instead
+of any time a client requests an operation.
+The pattern is: retry only after at least
+.I interval
+seconds elapsed since last attempt, for exactly
+.I num
+times; then use the next pattern.
+If
+.I num
+for the last pattern is "\fB+\fP", it retries forever; otherwise, 
+no more retries occur.
+This directive must appear before any target specification;
+it affects all targets with the same pattern.
+
 .TP
 .B rebind-as-user {NO|yes}
 If this option is given, the client's bind credentials are remembered
@@ -152,20 +172,30 @@ or when chasing a referral, if
 is set to
 .IR yes .
 
+.TP
+.B single\-conn {NO|yes}
+Discards current cached connection when the client rebinds.
+
+.TP
+.B use-temporary-conn {NO|yes}
+when set to 
+.BR yes ,
+create a temporary connection whenever competing with other threads
+for a shared one; otherwise, wait until the shared connection is available.
+
 .SH TARGET SPECIFICATION
 Target specification starts with a "uri" directive:
 
 .TP
-.B uri <protocol>://[<host>[:<port>]]/<naming context>
-The "server" directive that was allowed in the LDAP backend (although
-deprecated) has been completely discarded in the Meta backend.
+.B uri <protocol>://[<host>]/<naming context> [...]
 The <protocol> part can be anything
 .BR ldap_initialize (3)
-accepts ({ldap|ldaps|ldapi} and variants); <host> and <port> may be
+accepts ({ldap|ldaps|ldapi} and variants); the <host> may be
 omitted, defaulting to whatever is set in
 .BR ldap.conf (5).
-The <naming context> part is mandatory.
-It must end with one of the naming contexts defined for the backend,
+The <naming context> part is \fImandatory\fP for the first URI,
+but it \fImust be omitted\fP for subsequent ones, if any.
+The naming context part must be within the naming context defined for the backend,
 e.g.:
 .LP
 .RS
@@ -178,25 +208,25 @@ uri    "ldap://x.foo.com/dc=x,\fBdc=foo,dc=com\fP"
 .RS
 The <naming context> part doesn't need to be unique across the targets;
 it may also match one of the values of the "suffix" directive.
-Multiple URIs may be defined in a single argument.  The URIs must
-be separated by TABs (e.g. '\\t'; commas or spaces, unlike back-ldap,
-will not work,
-because they are legal in the <naming context>, and we don't want to use
-URL-encoded <naming context>s), and the additional URIs must have
-no <naming context> part.  This causes the underlying library
+Multiple URIs may be defined in a single URI statement.
+The additional URIs must be separate arguments and must not have any
+<naming context> part.  This causes the underlying library
 to contact the first server of the list that responds.
 For example, if \fIl1.foo.com\fP and \fIl2.foo.com\fP are shadows
 of the same server, the directive
 .LP
 .nf
 suffix "\fBdc=foo,dc=com\fP"
-uri    "ldap://l1.foo.com/\fBdc=foo,dc=com\fP  ldap://l2.foo.com/"
+uri    "ldap://l1.foo.com/\fBdc=foo,dc=com\fP" "ldap://l2.foo.com/"
 .fi
 
 .RE
 .RS
 causes \fIl2.foo.com\fP to be contacted whenever \fIl1.foo.com\fP
 does not respond.
+In that case, the URI list is internally rearranged, by moving unavailable
+URIs to the end, so that further connection attempts occur with respect to
+the last URI that succeeded.
 .RE
 
 .TP
@@ -340,22 +370,35 @@ If set before any target specification, it affects all targets, unless
 overridden by any per-target directive.
 
 .TP
-.B timeout [{add|delete|modify|modrdn}=]<seconds> [...]
-This directive allows to set per-database, per-target and per-operation
-timeouts.
-If no operation is specified, it affects all.
-Currently, only write operations are addressed, because searches
-can already be limited by means of the
-.B limits
-directive (see 
+.B timeout [<op>=]<val> [...]
+This directive allows to set per-operation timeouts.
+Operations can be
+
+\fB<op> ::= bind, add, delete, modrdn, modify, compare, search\fP
+
+The overall duration of the \fBsearch\fP operation is controlled either
+by the \fBtimelimit\fP parameter or by server-side enforced
+time limits (see \fBtimelimit\fP and \fBlimits\fP in
 .BR slapd.conf (5)
-for details), and other operations are not supposed to incur into the
-need for timeouts.
-Note: if the timelimit is exceeded, the operation is abandoned;
-the protocol does not provide any means to rollback the operation,
-so the client will not know if the operation eventually succeeded or not.
-If set before any target specification, it affects all targets, unless
-overridden by any per-target directive.
+for details).
+This \fBtimeout\fP parameter controls how long the target can be 
+irresponsive before the operation is aborted.
+Timeout is meaningless for the remaining operations,
+\fBunbind\fP and \fBabandon\fP, which do not imply any response,
+while it is not yet implemented in currently supported \fBextended\fP 
+operations.
+If no operation is specified, the timeout \fBval\fP affects all
+supported operations.
+If specified before any target definition, it affects all targets
+unless overridden by per-target directives.
+
+Note: if the timeout is exceeded, the operation is cancelled
+(according to the \fBcancel\fP directive);
+the protocol does not provide any means to rollback operations,
+so the client will not be notified about the result of the operation,
+which may eventually succeeded or not.
+In case the timeout is exceeded during a bind operation, the connection
+is destroyed, according to RFC4511.
 
 .TP
 .B tls {[try-]start|[try-]propagate}
index f737dc751c992a95ca4123a24b173dcff098a708..b1e0113014aea8357b87947d57a5e37202484b71 100644 (file)
@@ -111,28 +111,18 @@ meta_back_db_config(
        /* URI of server to query */
        if ( strcasecmp( argv[ 0 ], "uri" ) == 0 ) {
                int             i = mi->mi_ntargets;
-               LDAPURLDesc     *ludp, *tmpludp;
+               LDAPURLDesc     *ludp;
                struct berval   dn;
                int             rc;
                int             c;
-               BackendDB       *tmp_bd;
 
                metatarget_t    *mt;
+
+               char            **uris = NULL;
                
-               switch ( argc ) {
-               case 1:
+               if ( argc == 1 ) {
                        Debug( LDAP_DEBUG_ANY,
        "%s: line %d: missing URI "
-       "in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
-                               fname, lineno, 0 );
-                       return 1;
-
-               case 2:
-                       break;
-
-               default:
-                       Debug( LDAP_DEBUG_ANY,
-       "%s: line %d: too many args "
        "in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
                                fname, lineno, 0 );
                        return 1;
@@ -168,7 +158,6 @@ meta_back_db_config(
                mt = mi->mi_targets[ i ];
 
                mt->mt_rebind_f = mi->mi_rebind_f;
-               mt->mt_urllist_p = mt;
 
                mt->mt_nretries = mi->mi_nretries;
                mt->mt_quarantine = mi->mi_quarantine;
@@ -183,92 +172,122 @@ meta_back_db_config(
                        mt->mt_timeout[ c ] = mi->mi_timeout[ c ];
                }
 
-               /*
-                * uri MUST be legal!
-                */
-               if ( ldap_url_parselist_ext( &ludp, argv[ 1 ], "\t" ) != LDAP_SUCCESS )
-               {
-                       Debug( LDAP_DEBUG_ANY,
-       "%s: line %d: unable to parse URI"
-       " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
-                               fname, lineno, 0 );
-                       return 1;
-               }
+               for ( c = 1; c < argc; c++ ) {
+                       char    **tmpuris = ldap_str2charray( argv[ c ], "\t" );
 
-               /*
-                * uri MUST have the <dn> part!
-                */
-               if ( ludp->lud_dn == NULL ) {
-                       Debug( LDAP_DEBUG_ANY,
-       "%s: line %d: missing <naming context> "
+                       if ( tmpuris == NULL ) {
+                               Debug( LDAP_DEBUG_ANY,
+       "%s: line %d: unable to parse URIs #%d"
        " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
-                               fname, lineno, 0 );
-                       return 1;
+                               fname, lineno, c - 1 );
+                               return 1;
+                       }
 
-               } else if ( ludp->lud_dn[ 0 ] == '\0' ) {
-                       int     j = -1;
+                       if ( c == 0 ) {
+                               uris = tmpuris;
 
-                       for ( j = 0; !BER_BVISNULL( &be->be_nsuffix[ j ] ); j++ ) {
-                               if ( BER_BVISEMPTY( &be->be_nsuffix[ j ] ) ) {
-                                       break;
-                               }
+                       } else {
+                               ldap_charray_merge( &uris, tmpuris );
+                               ldap_charray_free( tmpuris );
                        }
+               }
 
-                       if ( BER_BVISNULL( &be->be_nsuffix[ j ] ) ) {
+               for ( c = 0; uris[ c ] != NULL; c++ ) {
+                       char *tmpuri = NULL;
+
+                       /*
+                        * uri MUST be legal!
+                        */
+                       if ( ldap_url_parselist_ext( &ludp, uris[ c ], "\t" ) != LDAP_SUCCESS
+                               || ludp->lud_next != NULL )
+                       {
                                Debug( LDAP_DEBUG_ANY,
-               "%s: line %d: missing <naming context> "
+               "%s: line %d: unable to parse URI #%d"
                " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
-                                       fname, lineno, 0 );
+                                       fname, lineno, c );
+                               ldap_charray_free( uris );
                                return 1;
                        }
-               }
 
-               /*
-                * copies and stores uri and suffix
-                */
-               ber_str2bv( ludp->lud_dn, 0, 0, &dn );
-               rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix,
-                       &mt->mt_nsuffix, NULL );
-               if( rc != LDAP_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                               "target \"%s\" DN is invalid\n",
-                               fname, lineno, argv[ 1 ] );
-                       return( 1 );
-               }
+                       if ( c == 0 ) {
 
-               ludp->lud_dn[ 0 ] = '\0';
+                               /*
+                                * uri MUST have the <dn> part!
+                                */
+                               if ( ludp->lud_dn == NULL ) {
+                                       Debug( LDAP_DEBUG_ANY,
+                       "%s: line %d: missing <naming context> "
+                       " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
+                                               fname, lineno, 0 );
+                                       ldap_free_urllist( ludp );
+                                       ldap_charray_free( uris );
+                                       return 1;
+                               }
 
-               switch ( ludp->lud_scope ) {
-               case LDAP_SCOPE_DEFAULT:
-                       mt->mt_scope = LDAP_SCOPE_SUBTREE;
-                       break;
+                               /*
+                                * copies and stores uri and suffix
+                                */
+                               ber_str2bv( ludp->lud_dn, 0, 0, &dn );
+                               rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix,
+                                       &mt->mt_nsuffix, NULL );
+                               if ( rc != LDAP_SUCCESS ) {
+                                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                                               "target \"%s\" DN is invalid\n",
+                                               fname, lineno, argv[ 1 ] );
+                                       ldap_free_urllist( ludp );
+                                       ldap_charray_free( uris );
+                                       return( 1 );
+                               }
 
-               case LDAP_SCOPE_SUBTREE:
-               case LDAP_SCOPE_SUBORDINATE:
-                       mt->mt_scope = ludp->lud_scope;
-                       break;
+                               ludp->lud_dn[ 0 ] = '\0';
 
-               default:
-                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                               "invalid scope for target \"%s\"\n",
-                               fname, lineno, argv[ 1 ] );
-                       return( 1 );
-               }
+                               switch ( ludp->lud_scope ) {
+                               case LDAP_SCOPE_DEFAULT:
+                                       mt->mt_scope = LDAP_SCOPE_SUBTREE;
+                                       break;
+
+                               case LDAP_SCOPE_SUBTREE:
+                               case LDAP_SCOPE_SUBORDINATE:
+                                       mt->mt_scope = ludp->lud_scope;
+                                       break;
+
+                               default:
+                                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                                               "invalid scope for target \"%s\"\n",
+                                               fname, lineno, argv[ 1 ] );
+                                       ldap_free_urllist( ludp );
+                                       ldap_charray_free( uris );
+                                       return( 1 );
+                               }
+
+                       } else {
+                               /* check all, to apply the scope check on the first one */
+                               if ( ludp->lud_dn != NULL && ludp->lud_dn[ 0 ] != '\0' ) {
+                                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+                                               "multiple URIs must have "
+                                               "no DN part\n",
+                                               fname, lineno, 0 );
+                                       ldap_free_urllist( ludp );
+                                       ldap_charray_free( uris );
+                                       return( 1 );
+
+                               }
+                       }
 
-               /* check all, to apply the scope check on the first one */
-               for ( tmpludp = ludp; tmpludp; tmpludp = tmpludp->lud_next ) {
-                       if ( tmpludp->lud_dn != NULL && tmpludp->lud_dn[ 0 ] != '\0' ) {
-                               Debug( LDAP_DEBUG_ANY, "%s: line %d: "
-                                       "multiple URIs must have "
-                                       "no DN part\n",
+                       tmpuri = ldap_url_list2urls( ludp );
+                       ldap_free_urllist( ludp );
+                       if ( tmpuri == NULL ) {
+                               Debug( LDAP_DEBUG_ANY, "%s: line %d: no memory?\n",
                                        fname, lineno, 0 );
+                               ldap_charray_free( uris );
                                return( 1 );
-
                        }
+                       ldap_memfree( uris[ c ] );
+                       uris[ c ] = tmpuri;
                }
 
-               mt->mt_uri = ldap_url_list2urls( ludp );
-               ldap_free_urllist( ludp );
+               mt->mt_uri = ldap_charray2str( uris, " " );
+               ldap_charray_free( uris );
                if ( mt->mt_uri == NULL) {
                        Debug( LDAP_DEBUG_ANY, "%s: line %d: no memory?\n",
                                fname, lineno, 0 );
@@ -278,11 +297,15 @@ meta_back_db_config(
                /*
                 * uri MUST be a branch of suffix!
                 */
-               tmp_bd = select_backend( &mt->mt_nsuffix, 0, 0 );
-               if ( tmp_bd == NULL || tmp_bd->be_private != be->be_private )
-               {
+               for ( c = 0; !BER_BVISNULL( &be->be_nsuffix[ c ] ); c++ ) {
+                       if ( dnIsSuffix( &mt->mt_nsuffix, &be->be_nsuffix[ c ] ) ) {
+                               break;
+                       }
+               }
+
+               if ( BER_BVISNULL( &be->be_nsuffix[ c ] ) ) {
                        Debug( LDAP_DEBUG_ANY,
-       "%s: line %d: <naming context> of URI does not resolve to this database.\n",
+       "%s: line %d: <naming context> of URI must be within the naming context of this database.\n",
                                fname, lineno, 0 );
                        return 1;
                }
@@ -1225,7 +1248,7 @@ idassert-authzFrom        "dn:<rootdn>"
        /* dn massaging */
        } else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) {
                BackendDB       *tmp_bd;
-               int             i = mi->mi_ntargets - 1, rc;
+               int             i = mi->mi_ntargets - 1, c, rc;
                struct berval   dn, nvnc, pvnc, nrnc, prnc;
 
                if ( i < 0 ) {
@@ -1260,11 +1283,16 @@ idassert-authzFrom      "dn:<rootdn>"
                                        fname, lineno, argv[ 1 ] );
                        return 1;
                }
-               
-               tmp_bd = select_backend( &nvnc, 0, 0 );
-               if ( tmp_bd != NULL && tmp_bd->be_private != be->be_private ) {
-                       Debug( LDAP_DEBUG_ANY, 
-       "%s: line %d: <suffix> \"%s\" already in use by another database, in "
+
+               for ( c = 0; !BER_BVISNULL( &be->be_nsuffix[ c ] ); c++ ) {
+                       if ( dnIsSuffix( &nvnc, &be->be_nsuffix[ 0 ] ) ) {
+                               break;
+                       }
+               }
+
+               if ( BER_BVISNULL( &be->be_nsuffix[ c ] ) ) {
+                       Debug( LDAP_DEBUG_ANY, "%s: line %d: "
+       "%s: line %d: <suffix> \"%s\" must be within the database naming context, in "
        "\"suffixMassage <suffix> <massaged suffix>\"\n",
                                fname, lineno, pvnc.bv_val );
                        free( pvnc.bv_val );
@@ -1285,12 +1313,9 @@ idassert-authzFrom       "dn:<rootdn>"
                tmp_bd = select_backend( &nrnc, 0, 0 );
                if ( tmp_bd != NULL && tmp_bd->be_private == be->be_private ) {
                        Debug( LDAP_DEBUG_ANY, 
-       "%s: line %d: warning: <massaged suffix> \"%s\" point to this database, in "
+       "%s: line %d: warning: <massaged suffix> \"%s\" resolves to this database, in "
        "\"suffixMassage <suffix> <massaged suffix>\"\n",
                                fname, lineno, prnc.bv_val );
-                       free( pvnc.bv_val );
-                       free( nvnc.bv_val );
-                       return 1;                                               
                }
 
                /*