]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-meta/config.c
better fix: in case of error during bind, just bail out (very conservative, though)
[openldap] / servers / slapd / back-meta / config.c
index 8457cf8510e76f5698bb8c57a2f5dbc5e2ed6b1f..18f3a772d96646dbb84d57fd57efcff6d0be0849 100644 (file)
@@ -69,6 +69,21 @@ new_target(
        return 0;
 }
 
+static int
+check_true_false( char *str )
+{
+       if ( strcasecmp( str, "true" ) == 0 || strcasecmp( str, "yes" ) == 0 ) {
+               return 1;
+       }
+
+       if ( strcasecmp( str, "false" ) == 0 || strcasecmp( str, "no" ) == 0 ) {
+               return 0;
+       }
+
+       return -1;
+}
+
+
 int
 meta_back_db_config(
                BackendDB       *be,
@@ -96,11 +111,30 @@ meta_back_db_config(
                LDAPURLDesc     *ludp, *tmpludp;
                struct berval   dn;
                int             rc;
+               int             c;
                
-               if ( argc != 2 ) {
+               switch ( argc ) {
+               case 1:
                        fprintf( stderr,
-       "%s: line %d: missing address"
-       " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
+       "%s: line %d: missing URI "
+       "in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
+                               fname, lineno );
+                       return 1;
+
+               case 2:
+                       break;
+
+               default:
+                       fprintf( stderr,
+       "%s: line %d: too many args "
+       "in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
+                               fname, lineno );
+                       return 1;
+               }
+
+               if ( be->be_nsuffix == NULL ) {
+                       fprintf( stderr,
+       "%s: line %d: the suffix must be defined before any target.\n",
                                fname, lineno );
                        return 1;
                }
@@ -129,6 +163,10 @@ meta_back_db_config(
                mi->mi_targets[ i ].mt_flags = mi->flags;
                mi->mi_targets[ i ].mt_version = mi->mi_version;
 
+               for ( c = 0; c < META_OP_LAST; c++ ) {
+                       mi->mi_targets[ i ].mt_timeout[ c ] = mi->mi_timeout[ c ];
+               }
+
                /*
                 * uri MUST be legal!
                 */
@@ -143,20 +181,35 @@ meta_back_db_config(
                /*
                 * uri MUST have the <dn> part!
                 */
-               if ( ludp->lud_dn == NULL || ludp->lud_dn[ 0 ] == '\0' ) {
+               if ( ludp->lud_dn == NULL ) {
                        fprintf( stderr,
        "%s: line %d: missing <naming context> "
        " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
                                fname, lineno );
                        return 1;
+
+               } else if ( ludp->lud_dn[ 0 ] == '\0' ) {
+                       int     j = -1;
+
+                       for ( j = 0; !BER_BVISNULL( &be->be_nsuffix[ j ] ); j++ ) {
+                               if ( BER_BVISEMPTY( &be->be_nsuffix[ j ] ) ) {
+                                       break;
+                               }
+                       }
+
+                       if ( BER_BVISNULL( &be->be_nsuffix[ j ] ) ) {
+                               fprintf( stderr,
+               "%s: line %d: missing <naming context> "
+               " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n",
+                                       fname, lineno );
+                               return 1;
+                       }
                }
 
                /*
                 * copies and stores uri and suffix
                 */
-               dn.bv_val = ludp->lud_dn;
-               dn.bv_len = strlen( ludp->lud_dn );
-
+               ber_str2bv( ludp->lud_dn, 0, 0, &dn );
                rc = dnPrettyNormal( NULL, &dn, &mi->mi_targets[ i ].mt_psuffix,
                        &mi->mi_targets[ i ].mt_nsuffix, NULL );
                if( rc != LDAP_SUCCESS ) {
@@ -168,6 +221,25 @@ meta_back_db_config(
 
                ludp->lud_dn[ 0 ] = '\0';
 
+               switch ( ludp->lud_scope ) {
+               case LDAP_SCOPE_DEFAULT:
+                       mi->mi_targets[ i ].mt_scope = LDAP_SCOPE_SUBTREE;
+                       break;
+
+               case LDAP_SCOPE_SUBTREE:
+#ifdef LDAP_SCOPE_SUBORDINATE
+               case LDAP_SCOPE_SUBORDINATE:
+#endif /* LDAP_SCOPE_SUBORDINATE */
+                       mi->mi_targets[ i ].mt_scope = ludp->lud_scope;
+                       break;
+
+               default:
+                       fprintf( stderr, "%s: line %d: "
+                                       "invalid scope for target '%s'\n",
+                                       fname, lineno, argv[ 1 ] );
+                       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' ) {
@@ -178,10 +250,6 @@ meta_back_db_config(
                                return( 1 );
 
                        }
-
-                       if ( tmpludp->lud_scope == LDAP_SCOPE_BASE ) {
-                               tmpludp->lud_scope = LDAP_SCOPE_DEFAULT;
-                       }
                }
 
                mi->mi_targets[ i ].mt_uri = ldap_url_list2urls( ludp );
@@ -351,14 +419,36 @@ meta_back_db_config(
                
        /* save bind creds for referral rebinds? */
        } else if ( strcasecmp( argv[ 0 ], "rebind-as-user" ) == 0 ) {
-               if (argc != 1) {
+               if ( argc > 2 ) {
                        fprintf( stderr,
-       "%s: line %d: rebind-as-user takes no arguments\n",
+       "%s: line %d: \"rebind-as-user {NO|yes}\" takes 1 argument.\n",
                            fname, lineno );
                        return( 1 );
                }
 
-               mi->flags |= LDAP_BACK_F_SAVECRED;
+               if ( argc == 1 ) {
+                       fprintf( stderr,
+       "%s: line %d: deprecated use of \"rebind-as-user {FALSE|true}\" with no arguments.\n",
+                           fname, lineno );
+                       mi->flags |= LDAP_BACK_F_SAVECRED;
+
+               } else {
+                       switch ( check_true_false( argv[ 1 ] ) ) {
+                       case 0:
+                               mi->flags &= ~LDAP_BACK_F_SAVECRED;
+                               break;
+
+                       case 1:
+                               mi->flags |= LDAP_BACK_F_SAVECRED;
+                               break;
+
+                       default:
+                               fprintf( stderr,
+       "%s: line %d: \"rebind-as-user {FALSE|true}\" unknown argument \"%s\".\n",
+                                   fname, lineno, argv[ 1 ] );
+                               return 1;
+                       }
+               }
 
        } else if ( strcasecmp( argv[ 0 ], "chase-referrals" ) == 0 ) {
                unsigned        *flagsp = mi->mi_ntargets ?
@@ -367,21 +457,24 @@ meta_back_db_config(
 
                if ( argc != 2 ) {
                        fprintf( stderr,
-       "%s: line %d: \"chase-referrals\" needs 1 argument.\n",
+       "%s: line %d: \"chase-referrals {TRUE|false}\" needs 1 argument.\n",
                                        fname, lineno );
                        return( 1 );
                }
 
                /* this is the default; we add it because the default might change... */
-               if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 1:
                        *flagsp |= LDAP_BACK_F_CHASE_REFERRALS;
+                       break;
 
-               } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+               case 0:
                        *flagsp &= ~LDAP_BACK_F_CHASE_REFERRALS;
+                       break;
 
-               } else {
+               default:
                        fprintf( stderr,
-               "%s: line %d: \"chase-referrals {yes|no}\": unknown argument \"%s\".\n",
+               "%s: line %d: \"chase-referrals {TRUE|false}\": unknown argument \"%s\".\n",
                                        fname, lineno, argv[ 1 ] );
                        return( 1 );
                }
@@ -430,27 +523,141 @@ meta_back_db_config(
 
                if ( argc != 2 ) {
                        fprintf( stderr,
-               "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
+               "%s: line %d: \"t-f-support {FALSE|true|discover}\" needs 1 argument.\n",
                                        fname, lineno );
                        return( 1 );
                }
 
-               if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 0:
                        *flagsp &= ~(LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER);
+                       break;
 
-               } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
+               case 1:
                        *flagsp |= LDAP_BACK_F_SUPPORT_T_F;
+                       break;
 
-               } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
-                       *flagsp |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+               default:
+                       if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
+                               *flagsp |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
+
+                       } else {
+                               fprintf( stderr,
+       "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
+                                       fname, lineno, argv[ 1 ] );
+                               return 1;
+                       }
+                       break;
+               }
+
+       /* onerr? */
+       } else if ( strcasecmp( argv[ 0 ], "onerr" ) == 0 ) {
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"onerr {CONTINUE|stop}\" takes 1 argument\n",
+                           fname, lineno );
+                       return( 1 );
+               }
+
+               if ( strcasecmp( argv[ 1 ], "continue" ) == 0 ) {
+                       mi->flags &= ~META_BACK_F_ONERR_STOP;
+
+               } else if ( strcasecmp( argv[ 1 ], "stop" ) == 0 ) {
+                       mi->flags |= META_BACK_F_ONERR_STOP;
 
                } else {
                        fprintf( stderr,
-       "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
+       "%s: line %d: \"onerr {CONTINUE|stop}\": invalid arg \"%s\".\n",
                                fname, lineno, argv[ 1 ] );
                        return 1;
                }
 
+       /* bind-defer? */
+       } else if ( strcasecmp( argv[ 0 ], "pseudoroot-bind-defer" ) == 0 ) {
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\" takes 1 argument\n",
+                           fname, lineno );
+                       return( 1 );
+               }
+
+               switch ( check_true_false( argv[ 1 ] ) ) {
+               case 0:
+                       mi->flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
+                       break;
+
+               case 1:
+                       mi->flags |= META_BACK_F_DEFER_ROOTDN_BIND;
+                       break;
+
+               default:
+                       fprintf( stderr,
+       "%s: line %d: \"pseudoroot-bind-defer {FALSE|true}\": invalid arg \"%s\".\n",
+                               fname, lineno, argv[ 1 ] );
+                       return 1;
+               }
+
+       } else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) {
+               char    *sep, *next;
+               time_t  *tv = mi->mi_ntargets ?
+                               mi->mi_targets[ mi->mi_ntargets - 1 ].mt_timeout
+                               : mi->mi_timeout;
+               int     c;
+
+               if ( argc < 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: \"timeout [{add|delete|modify|modrdn}=]<val> [...]\" takes at least 1 argument\n",
+                           fname, lineno );
+                       return( 1 );
+               }
+
+               for ( c = 1; c < argc; c++ ) {
+                       time_t  *t = NULL, val;
+
+                       sep = strchr( argv[ c ], '=' );
+                       if ( sep != NULL ) {
+                               size_t  len = sep - argv[ c ];
+
+                               if ( strncasecmp( argv[ c ], "add", len ) == 0 ) {
+                                       t = &tv[ META_OP_ADD ];
+                               } else if ( strncasecmp( argv[ c ], "delete", len ) == 0 ) {
+                                       t = &tv[ META_OP_DELETE ];
+                               } else if ( strncasecmp( argv[ c ], "modify", len ) == 0 ) {
+                                       t = &tv[ META_OP_MODIFY ];
+                               } else if ( strncasecmp( argv[ c ], "modrdn", len ) == 0 ) {
+                                       t = &tv[ META_OP_MODRDN ];
+                               } else {
+                                       fprintf( stderr,
+               "%s: line %d: unknown operation \"%s\" for timeout #%d.\n",
+                                               fname, lineno, argv[ c ], c );
+                                       return 1;
+                               }
+                               sep++;
+       
+                       } else {
+                               sep = argv[ c ];
+                       }
+       
+                       val = strtoul( sep, &next, 10 );
+                       if ( next == sep || next[ 0 ] != '\0' ) {
+                               fprintf( stderr,
+               "%s: line %d: unable to parse value \"%s\" for timeout.\n",
+                                       fname, lineno, sep );
+                               return 1;
+                       }
+               
+                       if ( t ) {
+                               *t = val;
+       
+                       } else {
+                               int     i;
+       
+                               for ( i = 0; i < META_OP_LAST; i++ ) {
+                                       tv[ i ] = val;
+                               }
+                       }
+               }
+       
        /* name to use as pseudo-root dn */
        } else if ( strcasecmp( argv[ 0 ], "pseudorootdn" ) == 0 ) {
                int             i = mi->mi_ntargets - 1;
@@ -503,7 +710,7 @@ meta_back_db_config(
        /* dn massaging */
        } else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) {
                BackendDB       *tmp_be;
-               int             i = mi->mi_ntargets - 1;
+               int             i = mi->mi_ntargets - 1, rc;
                struct berval   dn, nvnc, pvnc, nrnc, prnc;
 
                if ( i < 0 ) {
@@ -531,8 +738,7 @@ meta_back_db_config(
                        return 1;
                }
 
-               dn.bv_val = argv[ 1 ];
-               dn.bv_len = strlen( argv[ 1 ] );
+               ber_str2bv( argv[ 1 ], 0, 0, &dn );
                if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
                        fprintf( stderr, "%s: line %d: "
                                        "suffix '%s' is invalid\n",
@@ -551,8 +757,7 @@ meta_back_db_config(
                        return 1;                                               
                }
 
-               dn.bv_val = argv[ 2 ];
-               dn.bv_len = strlen( argv[ 2 ] );
+               ber_str2bv( argv[ 2 ], 0, 0, &dn );
                if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
                        fprintf( stderr, "%s: line %d: "
                                        "massaged suffix '%s' is invalid\n",
@@ -583,8 +788,15 @@ meta_back_db_config(
                 * FIXME: no extra rewrite capabilities should be added
                 * to the database
                 */
-               return suffix_massage_config( mi->mi_targets[ i ].mt_rwmap.rwm_rw,
+               rc = suffix_massage_config( mi->mi_targets[ i ].mt_rwmap.rwm_rw,
                                &pvnc, &nvnc, &prnc, &nrnc );
+
+               free( pvnc.bv_val );
+               free( nvnc.bv_val );
+               free( prnc.bv_val );
+               free( nrnc.bv_val );
+
+               return rc;
                
        /* rewrite stuff ... */
        } else if ( strncasecmp( argv[ 0 ], "rewrite", 7 ) == 0 ) {
@@ -772,7 +984,20 @@ ldap_back_map_config(
                                /*
                                 * FIXME: this should become an err
                                 */
-                               goto error_return;
+                               /*
+                                * we create a fake "proxied" ad 
+                                * and add it here.
+                                */
+
+                               rc = slap_bv2undef_ad( &mapping->src,
+                                               &ad, &text, SLAP_AD_PROXIED );
+                               if ( rc != LDAP_SUCCESS ) {
+                                       fprintf( stderr,
+       "%s: line %d: source attributeType '%s': %d (%s)\n",
+                                               fname, lineno, src,
+                                               rc, text ? text : "" );
+                                       goto error_return;
+                               }
                        }
 
                        ad = NULL;
@@ -784,6 +1009,21 @@ ldap_back_map_config(
        "%s: line %d: warning, destination attributeType '%s' "
        "is not defined in schema\n",
                                fname, lineno, dst );
+
+                       /*
+                        * we create a fake "proxied" ad 
+                        * and add it here.
+                        */
+
+                       rc = slap_bv2undef_ad( &mapping->dst,
+                                       &ad, &text, SLAP_AD_PROXIED );
+                       if ( rc != LDAP_SUCCESS ) {
+                               fprintf( stderr,
+       "%s: line %d: source attributeType '%s': %d (%s)\n",
+                                       fname, lineno, dst,
+                                       rc, text ? text : "" );
+                               return 1;
+                       }
                }
        }
 
@@ -824,6 +1064,10 @@ suffix_massage_regexize( const char *s )
        const char *p, *r;
        int i;
 
+       if ( s[ 0 ] == '\0' ) {
+               return ch_strdup( "^(.+)$" );
+       }
+
        for ( i = 0, p = s; 
                        ( r = strchr( p, ',' ) ) != NULL; 
                        p = r + 1, i++ )
@@ -831,10 +1075,11 @@ suffix_massage_regexize( const char *s )
 
        res = ch_calloc( sizeof( char ),
                        strlen( s )
-                       + STRLENOF( "(.+,)?" )
-                       + STRLENOF( "[ ]?" ) * i + 1 );
+                       + STRLENOF( "((.+),)?" )
+                       + STRLENOF( "[ ]?" ) * i
+                       + STRLENOF( "$" ) + 1 );
 
-       ptr = lutil_strcopy( res, "(.+,)?" );
+       ptr = lutil_strcopy( res, "((.+),)?" );
        for ( i = 0, p = s;
                        ( r = strchr( p, ',' ) ) != NULL;
                        p = r + 1 , i++ ) {
@@ -845,26 +1090,37 @@ suffix_massage_regexize( const char *s )
                        r++;
                }
        }
-       lutil_strcopy( ptr, p );
+       ptr = lutil_strcopy( ptr, p );
+       ptr[ 0 ] = '$';
+       ptr++;
+       ptr[ 0 ] = '\0';
 
        return res;
 }
 
 static char *
-suffix_massage_patternize( const char *s )
+suffix_massage_patternize( const char *s, const char *p )
 {
        ber_len_t       len;
-       char            *res;
+       char            *res, *ptr;
 
-       len = strlen( s );
+       len = strlen( p );
+
+       if ( s[ 0 ] == '\0' ) {
+               len++;
+       }
 
        res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 );
        if ( res == NULL ) {
                return NULL;
        }
 
-       strcpy( res, "%1" );
-       strcpy( &res[ STRLENOF( "%1" ) ], s );
+       ptr = lutil_strcopy( res, ( p[ 0 ] == '\0' ? "%2" : "%1" ) );
+       if ( s[ 0 ] == '\0' ) {
+               ptr[ 0 ] = ',';
+               ptr++;
+       }
+       lutil_strcopy( ptr, p );
 
        return res;
 }
@@ -893,12 +1149,21 @@ suffix_massage_config(
 
        rargv[ 0 ] = "rewriteRule";
        rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
-       rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val );
+       rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val, prnc->bv_val );
        rargv[ 3 ] = ":";
        rargv[ 4 ] = NULL;
        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
        ch_free( rargv[ 1 ] );
        ch_free( rargv[ 2 ] );
+
+       if ( BER_BVISEMPTY( pvnc ) ) {
+               rargv[ 0 ] = "rewriteRule";
+               rargv[ 1 ] = "^$";
+               rargv[ 2 ] = prnc->bv_val;
+               rargv[ 3 ] = ":";
+               rargv[ 4 ] = NULL;
+               rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
+       }
        
        rargv[ 0 ] = "rewriteContext";
        rargv[ 1 ] = "searchEntryDN";
@@ -907,13 +1172,22 @@ suffix_massage_config(
 
        rargv[ 0 ] = "rewriteRule";
        rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
-       rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val );
+       rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val, pvnc->bv_val );
        rargv[ 3 ] = ":";
        rargv[ 4 ] = NULL;
        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
        ch_free( rargv[ 1 ] );
        ch_free( rargv[ 2 ] );
 
+       if ( BER_BVISEMPTY( prnc ) ) {
+               rargv[ 0 ] = "rewriteRule";
+               rargv[ 1 ] = "^$";
+               rargv[ 2 ] = pvnc->bv_val;
+               rargv[ 3 ] = ":";
+               rargv[ 4 ] = NULL;
+               rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
+       }
+       
        /* backward compatibility */
        rargv[ 0 ] = "rewriteContext";
        rargv[ 1 ] = "searchResult";