Back to index

openldap  2.4.31
config.c
Go to the documentation of this file.
00001 /* config.c - configuration file handling routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 
00027 #include "portable.h"
00028 
00029 #include <stdio.h>
00030 
00031 #include <ac/string.h>
00032 #include <ac/ctype.h>
00033 #include <ac/signal.h>
00034 #include <ac/socket.h>
00035 #include <ac/errno.h>
00036 #include <ac/unistd.h>
00037 
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 
00041 #ifndef S_ISREG
00042 #define       S_ISREG(m)    (((m) & _S_IFMT) == _S_IFREG)
00043 #endif
00044 
00045 #include "slap.h"
00046 #ifdef LDAP_SLAPI
00047 #include "slapi/slapi.h"
00048 #endif
00049 #include "lutil.h"
00050 #include "lutil_ldap.h"
00051 #include "config.h"
00052 
00053 #define ARGS_STEP    512
00054 
00055 /*
00056  * defaults for various global variables
00057  */
00058 slap_mask_t          global_allows = 0;
00059 slap_mask_t          global_disallows = 0;
00060 int           global_gentlehup = 0;
00061 int           global_idletimeout = 0;
00062 int           global_writetimeout = 0;
00063 char   *global_host = NULL;
00064 struct berval global_host_bv = BER_BVNULL;
00065 char   *global_realm = NULL;
00066 char   *sasl_host = NULL;
00067 char          **default_passwd_hash = NULL;
00068 struct berval default_search_base = BER_BVNULL;
00069 struct berval default_search_nbase = BER_BVNULL;
00070 
00071 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
00072 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
00073 
00074 int    slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
00075 int    slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
00076 
00077 char   *slapd_pid_file  = NULL;
00078 char   *slapd_args_file = NULL;
00079 
00080 int use_reverse_lookup = 0;
00081 
00082 #ifdef LDAP_SLAPI
00083 int slapi_plugins_used = 0;
00084 #endif
00085 
00086 static int fp_getline(FILE *fp, ConfigArgs *c);
00087 static void fp_getline_init(ConfigArgs *c);
00088 
00089 static char   *strtok_quote(char *line, char *sep, char **quote_ptr);
00090 static char *strtok_quote_ldif(char **line);
00091 
00092 ConfigArgs *
00093 new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **argv )
00094 {
00095        ConfigArgs *c;
00096        c = ch_calloc( 1, sizeof( ConfigArgs ) );
00097        if ( c == NULL ) return(NULL);
00098        c->be     = be; 
00099        c->fname  = fname;
00100        c->argc   = argc;
00101        c->argv   = argv; 
00102        c->lineno = lineno;
00103        snprintf( c->log, sizeof( c->log ), "%s: line %d", fname, lineno );
00104        return(c);
00105 }
00106 
00107 void
00108 init_config_argv( ConfigArgs *c )
00109 {
00110        c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
00111        c->argv_size = ARGS_STEP + 1;
00112 }
00113 
00114 ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
00115        int i;
00116 
00117        for(i = 0; Conf[i].name; i++)
00118               if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
00119                      (!strcasecmp(c->argv[0], Conf[i].name)) ) break;
00120        if ( !Conf[i].name ) return NULL;
00121        return Conf+i;
00122 }
00123 
00124 int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
00125        int rc, arg_user, arg_type, arg_syn, iarg;
00126        unsigned uiarg;
00127        long larg;
00128        unsigned long ularg;
00129        ber_len_t barg;
00130        
00131        if(Conf->arg_type == ARG_IGNORED) {
00132               Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
00133                      c->log, Conf->name, 0);
00134               return(0);
00135        }
00136        arg_type = Conf->arg_type & ARGS_TYPES;
00137        arg_user = Conf->arg_type & ARGS_USERLAND;
00138        arg_syn = Conf->arg_type & ARGS_SYNTAX;
00139 
00140        if((arg_type == ARG_DN) && c->argc == 1) {
00141               c->argc = 2;
00142               c->argv[1] = "";
00143        }
00144        if(Conf->min_args && (c->argc < Conf->min_args)) {
00145               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> missing <%s> argument",
00146                      c->argv[0], Conf->what ? Conf->what : "" );
00147               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", c->log, c->cr_msg, 0 );
00148               return(ARG_BAD_CONF);
00149        }
00150        if(Conf->max_args && (c->argc > Conf->max_args)) {
00151               char   *ignored = " ignored";
00152 
00153               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> extra cruft after <%s>",
00154                      c->argv[0], Conf->what );
00155 
00156               ignored = "";
00157               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s%s.\n",
00158                             c->log, c->cr_msg, ignored );
00159               return(ARG_BAD_CONF);
00160        }
00161        if((arg_syn & ARG_DB) && !c->be) {
00162               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> only allowed within database declaration",
00163                      c->argv[0] );
00164               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
00165                      c->log, c->cr_msg, 0);
00166               return(ARG_BAD_CONF);
00167        }
00168        if((arg_syn & ARG_PRE_BI) && c->bi) {
00169               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any backend %sdeclaration",
00170                      c->argv[0], (arg_syn & ARG_PRE_DB) ? "or database " : "" );
00171               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
00172                      c->log, c->cr_msg, 0 );
00173               return(ARG_BAD_CONF);
00174        }
00175        if((arg_syn & ARG_PRE_DB) && c->be && c->be != frontendDB) {
00176               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any database declaration",
00177                      c->argv[0] );
00178               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
00179                      c->log, c->cr_msg, 0);
00180               return(ARG_BAD_CONF);
00181        }
00182        if((arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
00183               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> old format not supported", c->argv[0] );
00184               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
00185                      c->log, c->cr_msg, 0);
00186               return(ARG_BAD_CONF);
00187        }
00188        if(arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET)) {
00189               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid config_table, arg_item is NULL",
00190                      c->argv[0] );
00191               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
00192                      c->log, c->cr_msg, 0);
00193               return(ARG_BAD_CONF);
00194        }
00195        c->type = arg_user;
00196        memset(&c->values, 0, sizeof(c->values));
00197        if(arg_type == ARG_STRING) {
00198               assert( c->argc == 2 );
00199               if ( !check_only )
00200                      c->value_string = ch_strdup(c->argv[1]);
00201        } else if(arg_type == ARG_BERVAL) {
00202               assert( c->argc == 2 );
00203               if ( !check_only )
00204                      ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
00205        } else if(arg_type == ARG_DN) {
00206               struct berval bv;
00207               assert( c->argc == 2 );
00208               ber_str2bv( c->argv[1], 0, 0, &bv );
00209               rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
00210               if ( rc != LDAP_SUCCESS ) {
00211                      snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid DN %d (%s)",
00212                             c->argv[0], rc, ldap_err2string( rc ));
00213                      Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg, 0);
00214                      return(ARG_BAD_CONF);
00215               }
00216               if ( check_only ) {
00217                      ch_free( c->value_ndn.bv_val );
00218                      ch_free( c->value_dn.bv_val );
00219               }
00220        } else if(arg_type == ARG_ATDESC) {
00221               const char *text = NULL;
00222               assert( c->argc == 2 );
00223               c->value_ad = NULL;
00224               rc = slap_str2ad( c->argv[1], &c->value_ad, &text );
00225               if ( rc != LDAP_SUCCESS ) {
00226                      snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid AttributeDescription %d (%s)",
00227                             c->argv[0], rc, text );
00228                      Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg, 0);
00229                      return(ARG_BAD_CONF);
00230               }
00231        } else {      /* all numeric */
00232               int j;
00233               iarg = 0; larg = 0; barg = 0;
00234               switch(arg_type) {
00235                      case ARG_INT:
00236                             assert( c->argc == 2 );
00237                             if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
00238                                    snprintf( c->cr_msg, sizeof( c->cr_msg ),
00239                                           "<%s> unable to parse \"%s\" as int",
00240                                           c->argv[0], c->argv[1] );
00241                                    Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
00242                                           c->log, c->cr_msg, 0);
00243                                    return(ARG_BAD_CONF);
00244                             }
00245                             break;
00246                      case ARG_UINT:
00247                             assert( c->argc == 2 );
00248                             if ( lutil_atoux( &uiarg, c->argv[1], 0 ) != 0 ) {
00249                                    snprintf( c->cr_msg, sizeof( c->cr_msg ),
00250                                           "<%s> unable to parse \"%s\" as unsigned int",
00251                                           c->argv[0], c->argv[1] );
00252                                    Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
00253                                           c->log, c->cr_msg, 0);
00254                                    return(ARG_BAD_CONF);
00255                             }
00256                             break;
00257                      case ARG_LONG:
00258                             assert( c->argc == 2 );
00259                             if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
00260                                    snprintf( c->cr_msg, sizeof( c->cr_msg ),
00261                                           "<%s> unable to parse \"%s\" as long",
00262                                           c->argv[0], c->argv[1] );
00263                                    Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
00264                                           c->log, c->cr_msg, 0);
00265                                    return(ARG_BAD_CONF);
00266                             }
00267                             break;
00268                      case ARG_ULONG:
00269                             assert( c->argc == 2 );
00270                             if ( lutil_atoulx( &ularg, c->argv[1], 0 ) != 0 ) {
00271                                    snprintf( c->cr_msg, sizeof( c->cr_msg ),
00272                                           "<%s> unable to parse \"%s\" as unsigned long",
00273                                           c->argv[0], c->argv[1] );
00274                                    Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
00275                                           c->log, c->cr_msg, 0);
00276                                    return(ARG_BAD_CONF);
00277                             }
00278                             break;
00279                      case ARG_BER_LEN_T: {
00280                             unsigned long l;
00281                             assert( c->argc == 2 );
00282                             if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
00283                                    snprintf( c->cr_msg, sizeof( c->cr_msg ),
00284                                           "<%s> unable to parse \"%s\" as ber_len_t",
00285                                           c->argv[0], c->argv[1] );
00286                                    Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
00287                                           c->log, c->cr_msg, 0);
00288                                    return(ARG_BAD_CONF);
00289                             }
00290                             barg = (ber_len_t)l;
00291                             } break;
00292                      case ARG_ON_OFF:
00293                             /* note: this is an explicit exception
00294                              * to the "need exactly 2 args" rule */
00295                             if (c->argc == 1) {
00296                                    iarg = 1;
00297                             } else if ( !strcasecmp(c->argv[1], "on") ||
00298                                    !strcasecmp(c->argv[1], "true") ||
00299                                    !strcasecmp(c->argv[1], "yes") )
00300                             {
00301                                    iarg = 1;
00302                             } else if ( !strcasecmp(c->argv[1], "off") ||
00303                                    !strcasecmp(c->argv[1], "false") ||
00304                                    !strcasecmp(c->argv[1], "no") )
00305                             {
00306                                    iarg = 0;
00307                             } else {
00308                                    snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
00309                                           c->argv[0] );
00310                                    Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
00311                                           c->log, c->cr_msg, 0 );
00312                                    return(ARG_BAD_CONF);
00313                             }
00314                             break;
00315               }
00316               j = (arg_type & ARG_NONZERO) ? 1 : 0;
00317               if(iarg < j && larg < j && barg < (unsigned)j ) {
00318                      larg = larg ? larg : (barg ? (long)barg : iarg);
00319                      snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
00320                             c->argv[0] );
00321                      Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
00322                             c->log, c->cr_msg, 0 );
00323                      return(ARG_BAD_CONF);
00324               }
00325               switch(arg_type) {
00326                      case ARG_ON_OFF:
00327                      case ARG_INT:        c->value_int = iarg;        break;
00328                      case ARG_UINT:              c->value_uint = uiarg;             break;
00329                      case ARG_LONG:              c->value_long = larg;              break;
00330                      case ARG_ULONG:             c->value_ulong = ularg;            break;
00331                      case ARG_BER_LEN_T:  c->value_ber_t = barg;             break;
00332               }
00333        }
00334        return 0;
00335 }
00336 
00337 int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
00338        int rc, arg_type;
00339        void *ptr = NULL;
00340 
00341        arg_type = Conf->arg_type;
00342        if(arg_type & ARG_MAGIC) {
00343               if(!c->be) c->be = frontendDB;
00344               c->cr_msg[0] = '\0';
00345               rc = (*((ConfigDriver*)Conf->arg_item))(c);
00346 #if 0
00347               if(c->be == frontendDB) c->be = NULL;
00348 #endif
00349               if(rc) {
00350                      if ( !c->cr_msg[0] ) {
00351                             snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> handler exited with %d",
00352                                    c->argv[0], rc );
00353                             Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
00354                                    c->log, c->cr_msg, 0 );
00355                      }
00356                      return(ARG_BAD_CONF);
00357               }
00358               return(0);
00359        }
00360        if(arg_type & ARG_OFFSET) {
00361               if (c->be && c->table == Cft_Database)
00362                      ptr = c->be->be_private;
00363               else if (c->bi)
00364                      ptr = c->bi->bi_private;
00365               else {
00366                      snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> offset is missing base pointer",
00367                             c->argv[0] );
00368                      Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
00369                             c->log, c->cr_msg, 0);
00370                      return(ARG_BAD_CONF);
00371               }
00372               ptr = (void *)((char *)ptr + (long)Conf->arg_item);
00373        } else if (arg_type & ARGS_TYPES) {
00374               ptr = Conf->arg_item;
00375        }
00376        if(arg_type & ARGS_TYPES)
00377               switch(arg_type & ARGS_TYPES) {
00378                      case ARG_ON_OFF:
00379                      case ARG_INT:               *(int*)ptr = c->value_int;                break;
00380                      case ARG_UINT:              *(unsigned*)ptr = c->value_uint;                 break;
00381                      case ARG_LONG:       *(long*)ptr = c->value_long;                     break;
00382                      case ARG_ULONG:      *(unsigned long*)ptr = c->value_ulong;                  break;
00383                      case ARG_BER_LEN_T:  *(ber_len_t*)ptr = c->value_ber_t;               break;
00384                      case ARG_STRING: {
00385                             char *cc = *(char**)ptr;
00386                             if(cc) {
00387                                    if ((arg_type & ARG_UNIQUE) && c->op == SLAP_CONFIG_ADD ) {
00388                                           Debug(LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
00389                                                  c->log, Conf->name, 0 );
00390                                           return(ARG_BAD_CONF);
00391                                    }
00392                                    ch_free(cc);
00393                             }
00394                             *(char **)ptr = c->value_string;
00395                             break;
00396                             }
00397                      case ARG_BERVAL:
00398                             *(struct berval *)ptr = c->value_bv;
00399                             break;
00400                      case ARG_ATDESC:
00401                             *(AttributeDescription **)ptr = c->value_ad;
00402                             break;
00403               }
00404        return(0);
00405 }
00406 
00407 int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
00408        int rc, arg_type;
00409 
00410        arg_type = Conf->arg_type;
00411        if(arg_type == ARG_IGNORED) {
00412               Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
00413                      c->log, Conf->name, 0);
00414               return(0);
00415        }
00416        rc = config_check_vals( Conf, c, 0 );
00417        if ( rc ) return rc;
00418        return config_set_vals( Conf, c );
00419 }
00420 
00421 int
00422 config_del_vals(ConfigTable *cf, ConfigArgs *c)
00423 {
00424        int rc = 0;
00425 
00426        /* If there is no handler, just ignore it */
00427        if ( cf->arg_type & ARG_MAGIC ) {
00428               c->argv[0] = cf->ad->ad_cname.bv_val;
00429               c->op = LDAP_MOD_DELETE;
00430               c->type = cf->arg_type & ARGS_USERLAND;
00431               rc = (*((ConfigDriver*)cf->arg_item))(c);
00432        }
00433        return rc;
00434 }
00435 
00436 int
00437 config_get_vals(ConfigTable *cf, ConfigArgs *c)
00438 {
00439        int rc = 0;
00440        struct berval bv;
00441        void *ptr;
00442 
00443        if ( cf->arg_type & ARG_IGNORED ) {
00444               return 1;
00445        }
00446 
00447        memset(&c->values, 0, sizeof(c->values));
00448        c->rvalue_vals = NULL;
00449        c->rvalue_nvals = NULL;
00450        c->op = SLAP_CONFIG_EMIT;
00451        c->type = cf->arg_type & ARGS_USERLAND;
00452 
00453        if ( cf->arg_type & ARG_MAGIC ) {
00454               rc = (*((ConfigDriver*)cf->arg_item))(c);
00455               if ( rc ) return rc;
00456        } else {
00457               if ( cf->arg_type & ARG_OFFSET ) {
00458                      if (c->be && c->table == Cft_Database)
00459                             ptr = c->be->be_private;
00460                      else if ( c->bi )
00461                             ptr = c->bi->bi_private;
00462                      else
00463                             return 1;
00464                      ptr = (void *)((char *)ptr + (long)cf->arg_item);
00465               } else {
00466                      ptr = cf->arg_item;
00467               }
00468               
00469               switch(cf->arg_type & ARGS_TYPES) {
00470               case ARG_ON_OFF:
00471               case ARG_INT: c->value_int = *(int *)ptr; break;
00472               case ARG_UINT:       c->value_uint = *(unsigned *)ptr; break;
00473               case ARG_LONG:       c->value_long = *(long *)ptr; break;
00474               case ARG_ULONG:      c->value_ulong = *(unsigned long *)ptr; break;
00475               case ARG_BER_LEN_T:  c->value_ber_t = *(ber_len_t *)ptr; break;
00476               case ARG_STRING:
00477                      if ( *(char **)ptr )
00478                             c->value_string = ch_strdup(*(char **)ptr);
00479                      break;
00480               case ARG_BERVAL:
00481                      c->value_bv = *((struct berval *)ptr); break;
00482               case ARG_ATDESC:
00483                      c->value_ad = *(AttributeDescription **)ptr; break;
00484               }
00485        }
00486        if ( cf->arg_type & ARGS_TYPES) {
00487               bv.bv_len = 0;
00488               bv.bv_val = c->log;
00489               switch(cf->arg_type & ARGS_TYPES) {
00490               case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
00491               case ARG_UINT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%u", c->value_uint); break;
00492               case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
00493               case ARG_ULONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%lu", c->value_ulong); break;
00494               case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
00495               case ARG_ON_OFF: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%s",
00496                      c->value_int ? "TRUE" : "FALSE"); break;
00497               case ARG_STRING:
00498                      if ( c->value_string && c->value_string[0]) {
00499                             ber_str2bv( c->value_string, 0, 0, &bv);
00500                      } else {
00501                             return 1;
00502                      }
00503                      break;
00504               case ARG_BERVAL:
00505                      if ( !BER_BVISEMPTY( &c->value_bv )) {
00506                             bv = c->value_bv;
00507                      } else {
00508                             return 1;
00509                      }
00510                      break;
00511               case ARG_ATDESC:
00512                      if ( c->value_ad ) {
00513                             bv = c->value_ad->ad_cname;
00514                      } else {
00515                             return 1;
00516                      }
00517                      break;
00518               default:
00519                      bv.bv_val = NULL;
00520                      break;
00521               }
00522               if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) {
00523                      return 1;
00524               }
00525               if (( cf->arg_type & ARGS_TYPES ) == ARG_STRING ) {
00526                      ber_bvarray_add(&c->rvalue_vals, &bv);
00527               } else if ( !BER_BVISNULL( &bv ) ) {
00528                      value_add_one(&c->rvalue_vals, &bv);
00529               }
00530               /* else: maybe c->rvalue_vals already set? */
00531        }
00532        return rc;
00533 }
00534 
00535 int
00536 init_config_attrs(ConfigTable *ct) {
00537        int i, code;
00538 
00539        for (i=0; ct[i].name; i++ ) {
00540               if ( !ct[i].attribute ) continue;
00541               code = register_at( ct[i].attribute, &ct[i].ad, 1 );
00542               if ( code ) {
00543                      fprintf( stderr, "init_config_attrs: register_at failed\n" );
00544                      return code;
00545               }
00546        }
00547 
00548        return 0;
00549 }
00550 
00551 int
00552 init_config_ocs( ConfigOCs *ocs ) {
00553        int i, code;
00554 
00555        for (i=0;ocs[i].co_def;i++) {
00556               code = register_oc( ocs[i].co_def, &ocs[i].co_oc, 1 );
00557               if ( code ) {
00558                      fprintf( stderr, "init_config_ocs: register_oc failed\n" );
00559                      return code;
00560               }
00561        }
00562        return 0;
00563 }
00564 
00565 /* Split an LDIF line into space-separated tokens. Words may be grouped
00566  * by quotes. A quoted string may begin in the middle of a word, but must
00567  * end at the end of the word (be followed by whitespace or EOS). Any other
00568  * quotes are passed through unchanged. All other characters are passed
00569  * through unchanged.
00570  */
00571 static char *
00572 strtok_quote_ldif( char **line )
00573 {
00574        char *beg, *ptr, *quote=NULL;
00575        int inquote=0;
00576 
00577        ptr = *line;
00578 
00579        if ( !ptr || !*ptr )
00580               return NULL;
00581 
00582        while( isspace( (unsigned char) *ptr )) ptr++;
00583 
00584        if ( *ptr == '"' ) {
00585               inquote = 1;
00586               ptr++;
00587        }
00588 
00589        beg = ptr;
00590 
00591        for (;*ptr;ptr++) {
00592               if ( *ptr == '"' ) {
00593                      if ( inquote && ( !ptr[1] || isspace((unsigned char) ptr[1]))) {
00594                             *ptr++ = '\0';
00595                             break;
00596                      }
00597                      inquote = 1;
00598                      quote = ptr;
00599                      continue;
00600               }
00601               if ( inquote )
00602                      continue;
00603               if ( isspace( (unsigned char) *ptr )) {
00604                      *ptr++ = '\0';
00605                      break;
00606               }
00607        }
00608        if ( quote ) {
00609               while ( quote < ptr ) {
00610                      *quote = quote[1];
00611                      quote++;
00612               }
00613        }
00614        if ( !*ptr ) {
00615               *line = NULL;
00616        } else {
00617               while ( isspace( (unsigned char) *ptr )) ptr++;
00618               *line = ptr;
00619        }
00620        return beg;
00621 }
00622 
00623 static void
00624 config_parse_ldif( ConfigArgs *c )
00625 {
00626        char *next;
00627        c->tline = ch_strdup(c->line);
00628        next = c->tline;
00629 
00630        while ((c->argv[c->argc] = strtok_quote_ldif( &next )) != NULL) {
00631               c->argc++;
00632               if ( c->argc >= c->argv_size ) {
00633                      char **tmp = ch_realloc( c->argv, (c->argv_size + ARGS_STEP) *
00634                             sizeof( *c->argv ));
00635                      c->argv = tmp;
00636                      c->argv_size += ARGS_STEP;
00637               }
00638        }
00639        c->argv[c->argc] = NULL;
00640 }
00641 
00642 int
00643 config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
00644 {
00645        int    rc = 0;
00646 
00647        snprintf( c->log, sizeof( c->log ), "%s: value #%d",
00648               ct->ad->ad_cname.bv_val, valx );
00649        c->argc = 1;
00650        c->argv[0] = ct->ad->ad_cname.bv_val;
00651 
00652        if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
00653               c->argv[c->argc] = c->line;
00654               c->argc++;
00655               c->argv[c->argc] = NULL;
00656               c->tline = NULL;
00657        } else {
00658               config_parse_ldif( c );
00659        }
00660        rc = config_check_vals( ct, c, 1 );
00661        ch_free( c->tline );
00662        c->tline = NULL;
00663 
00664        if ( rc )
00665               rc = LDAP_CONSTRAINT_VIOLATION;
00666 
00667        return rc;
00668 }
00669 
00670 int
00671 config_parse_add(ConfigTable *ct, ConfigArgs *c, int valx)
00672 {
00673        int    rc = 0;
00674 
00675        snprintf( c->log, sizeof( c->log ), "%s: value #%d",
00676               ct->ad->ad_cname.bv_val, valx );
00677        c->argc = 1;
00678        c->argv[0] = ct->ad->ad_cname.bv_val;
00679 
00680        if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
00681               c->argv[c->argc] = c->line;
00682               c->argc++;
00683               c->argv[c->argc] = NULL;
00684               c->tline = NULL;
00685        } else {
00686               config_parse_ldif( c );
00687        }
00688        c->op = LDAP_MOD_ADD;
00689        rc = config_add_vals( ct, c );
00690        ch_free( c->tline );
00691 
00692        return rc;
00693 }
00694 
00695 int
00696 read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
00697 {
00698        FILE *fp;
00699        ConfigTable *ct;
00700        ConfigArgs *c;
00701        int rc;
00702        struct stat s;
00703 
00704        c = ch_calloc( 1, sizeof( ConfigArgs ) );
00705        if ( c == NULL ) {
00706               return 1;
00707        }
00708 
00709        if ( depth ) {
00710               memcpy( c, cf, sizeof( ConfigArgs ) );
00711        } else {
00712               c->depth = depth; /* XXX */
00713               c->bi = NULL;
00714               c->be = NULL;
00715        }
00716 
00717        c->valx = -1;
00718        c->fname = fname;
00719        init_config_argv( c );
00720 
00721        if ( stat( fname, &s ) != 0 ) {
00722               ldap_syslog = 1;
00723               Debug(LDAP_DEBUG_ANY,
00724                   "could not stat config file \"%s\": %s (%d)\n",
00725                   fname, strerror(errno), errno);
00726               ch_free( c );
00727               return(1);
00728        }
00729 
00730        if ( !S_ISREG( s.st_mode ) ) {
00731               ldap_syslog = 1;
00732               Debug(LDAP_DEBUG_ANY,
00733                   "regular file expected, got \"%s\"\n",
00734                   fname, 0, 0 );
00735               ch_free( c );
00736               return(1);
00737        }
00738 
00739        fp = fopen( fname, "r" );
00740        if ( fp == NULL ) {
00741               ldap_syslog = 1;
00742               Debug(LDAP_DEBUG_ANY,
00743                   "could not open config file \"%s\": %s (%d)\n",
00744                   fname, strerror(errno), errno);
00745               ch_free( c );
00746               return(1);
00747        }
00748 
00749        Debug(LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0);
00750 
00751        fp_getline_init(c);
00752 
00753        c->tline = NULL;
00754 
00755        while ( fp_getline( fp, c ) ) {
00756               /* skip comments and blank lines */
00757               if ( c->line[0] == '#' || c->line[0] == '\0' ) {
00758                      continue;
00759               }
00760 
00761               snprintf( c->log, sizeof( c->log ), "%s: line %d",
00762                             c->fname, c->lineno );
00763 
00764               c->argc = 0;
00765               ch_free( c->tline );
00766               if ( config_fp_parse_line( c ) ) {
00767                      rc = 1;
00768                      goto done;
00769               }
00770 
00771               if ( c->argc < 1 ) {
00772                      Debug( LDAP_DEBUG_ANY, "%s: bad config line.\n",
00773                             c->log, 0, 0);
00774                      rc = 1;
00775                      goto done;
00776               }
00777 
00778               c->op = SLAP_CONFIG_ADD;
00779 
00780               ct = config_find_keyword( cft, c );
00781               if ( ct ) {
00782                      c->table = Cft_Global;
00783                      rc = config_add_vals( ct, c );
00784                      if ( !rc ) continue;
00785 
00786                      if ( rc & ARGS_USERLAND ) {
00787                             /* XXX a usertype would be opaque here */
00788                             Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
00789                                    c->log, c->argv[0], 0);
00790                             rc = 1;
00791                             goto done;
00792 
00793                      } else if ( rc == ARG_BAD_CONF ) {
00794                             rc = 1;
00795                             goto done;
00796                      }
00797                      
00798               } else if ( c->bi && !c->be ) {
00799                      rc = SLAP_CONF_UNKNOWN;
00800                      if ( c->bi->bi_cf_ocs ) {
00801                             ct = config_find_keyword( c->bi->bi_cf_ocs->co_table, c );
00802                             if ( ct ) {
00803                                    c->table = c->bi->bi_cf_ocs->co_type;
00804                                    rc = config_add_vals( ct, c );
00805                             }
00806                      }
00807                      if ( c->bi->bi_config && rc == SLAP_CONF_UNKNOWN ) {
00808                             rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno,
00809                                    c->argc, c->argv);
00810                      }
00811                      if ( rc ) {
00812                             switch(rc) {
00813                             case SLAP_CONF_UNKNOWN:
00814                                    Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
00815                                           "<%s> inside backend info definition.\n",
00816                                           c->log, *c->argv, 0);
00817                             default:
00818                                    rc = 1;
00819                                    goto done;
00820                             }
00821                      }
00822 
00823               } else if ( c->be && c->be != frontendDB ) {
00824                      rc = SLAP_CONF_UNKNOWN;
00825                      if ( c->be->be_cf_ocs ) {
00826                             ct = config_find_keyword( c->be->be_cf_ocs->co_table, c );
00827                             if ( ct ) {
00828                                    c->table = c->be->be_cf_ocs->co_type;
00829                                    rc = config_add_vals( ct, c );
00830                             }
00831                      }
00832                      if ( c->be->be_config && rc == SLAP_CONF_UNKNOWN ) {
00833                             rc = (*c->be->be_config)(c->be, c->fname, c->lineno,
00834                                    c->argc, c->argv);
00835                      }
00836                      if ( rc == SLAP_CONF_UNKNOWN && SLAP_ISGLOBALOVERLAY( frontendDB ) )
00837                      {
00838                             /* global overlays may need 
00839                              * definitions inside other databases...
00840                              */
00841                             rc = (*frontendDB->be_config)( frontendDB,
00842                                    c->fname, (int)c->lineno, c->argc, c->argv );
00843                      }
00844 
00845                      switch ( rc ) {
00846                      case 0:
00847                             break;
00848 
00849                      case SLAP_CONF_UNKNOWN:
00850                             Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
00851                                    "<%s> inside backend database definition.\n",
00852                                    c->log, *c->argv, 0);
00853                             
00854                      default:
00855                             rc = 1;
00856                             goto done;
00857                      }
00858 
00859               } else if ( frontendDB->be_config ) {
00860                      rc = (*frontendDB->be_config)( frontendDB,
00861                             c->fname, (int)c->lineno, c->argc, c->argv);
00862                      if ( rc ) {
00863                             switch(rc) {
00864                             case SLAP_CONF_UNKNOWN:
00865                                    Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
00866                                           "<%s> inside global database definition.\n",
00867                                           c->log, *c->argv, 0);
00868 
00869                             default:
00870                                    rc = 1;
00871                                    goto done;
00872                             }
00873                      }
00874                      
00875               } else {
00876                      Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
00877                             "<%s> outside backend info and database definitions.\n",
00878                             c->log, *c->argv, 0);
00879                      rc = 1;
00880                      goto done;
00881               }
00882        }
00883 
00884        rc = 0;
00885 
00886 done:
00887        if ( cf ) {
00888               cf->be = c->be;
00889               cf->bi = c->bi;
00890        }
00891        ch_free(c->tline);
00892        fclose(fp);
00893        ch_free(c->argv);
00894        ch_free(c);
00895        return(rc);
00896 }
00897 
00898 /* restrictops, allows, disallows, requires, loglevel */
00899 
00900 int
00901 bverb_to_mask(struct berval *bword, slap_verbmasks *v) {
00902        int i;
00903        for(i = 0; !BER_BVISNULL(&v[i].word); i++) {
00904               if(!ber_bvstrcasecmp(bword, &v[i].word)) break;
00905        }
00906        return(i);
00907 }
00908 
00909 int
00910 verb_to_mask(const char *word, slap_verbmasks *v) {
00911        struct berval bword;
00912        ber_str2bv( word, 0, 0, &bword );
00913        return bverb_to_mask( &bword, v );
00914 }
00915 
00916 int
00917 verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) {
00918        int i, j;
00919        for(i = 1; i < argc; i++) {
00920               j = verb_to_mask(argv[i], v);
00921               if(BER_BVISNULL(&v[j].word)) return i;
00922               while (!v[j].mask) j--;
00923               *m |= v[j].mask;
00924        }
00925        return(0);
00926 }
00927 
00928 /* Mask keywords that represent multiple bits should occur before single
00929  * bit keywords in the verbmasks array.
00930  */
00931 int
00932 mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) {
00933        int i, rc = 1;
00934 
00935        if (m) {
00936               for (i=0; !BER_BVISNULL(&v[i].word); i++) {
00937                      if (!v[i].mask) continue;
00938                      if (( m & v[i].mask ) == v[i].mask ) {
00939                             value_add_one( bva, &v[i].word );
00940                             rc = 0;
00941                             m ^= v[i].mask;
00942                             if ( !m ) break;
00943                      }
00944               }
00945        }
00946        return rc;
00947 }
00948 
00949 /* Return the verbs as a single string, separated by delim */
00950 int
00951 mask_to_verbstring(slap_verbmasks *v, slap_mask_t m0, char delim, struct berval *bv)
00952 {
00953        int i, rc = 1;
00954 
00955        BER_BVZERO( bv );
00956        if (m0) {
00957               slap_mask_t m = m0;
00958               char *ptr;
00959               for (i=0; !BER_BVISNULL(&v[i].word); i++) {
00960                      if (!v[i].mask) continue;
00961                      if (( m & v[i].mask ) == v[i].mask ) {
00962                             bv->bv_len += v[i].word.bv_len + 1;
00963                             rc = 0;
00964                             m ^= v[i].mask;
00965                             if ( !m ) break;
00966                      }
00967               }
00968               bv->bv_val = ch_malloc(bv->bv_len);
00969               bv->bv_len--;
00970               ptr = bv->bv_val;
00971               m = m0;
00972               for (i=0; !BER_BVISNULL(&v[i].word); i++) {
00973                      if (!v[i].mask) continue;
00974                      if (( m & v[i].mask ) == v[i].mask ) {
00975                             ptr = lutil_strcopy(ptr, v[i].word.bv_val);
00976                             *ptr++ = delim;
00977                             m ^= v[i].mask;
00978                             if ( !m ) break;
00979                      }
00980               }
00981               ptr[-1] = '\0';
00982        }
00983        return rc;
00984 }
00985 
00986 /* Parse a verbstring */
00987 int
00988 verbstring_to_mask(slap_verbmasks *v, char *str, char delim, slap_mask_t *m) {
00989        int j;
00990        char *d;
00991        struct berval bv;
00992 
00993        do {
00994               bv.bv_val = str;
00995               d = strchr( str, delim );
00996               if ( d )
00997                      bv.bv_len = d - str;
00998               else
00999                      bv.bv_len = strlen( str );
01000               j = bverb_to_mask( &bv, v );
01001               if(BER_BVISNULL(&v[j].word)) return 1;
01002               while (!v[j].mask) j--;
01003               *m |= v[j].mask;
01004               str += bv.bv_len + 1;
01005        } while ( d );
01006        return(0);
01007 }
01008 
01009 int
01010 slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
01011 {
01012        int           i;
01013 
01014        assert( *vp == NULL );
01015 
01016        for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */;
01017 
01018        *vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );
01019 
01020        for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
01021               ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
01022               *((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
01023        }
01024 
01025        BER_BVZERO( &(*vp)[ i ].word );
01026 
01027        return 0;            
01028 }
01029 
01030 int
01031 slap_verbmasks_destroy( slap_verbmasks *v )
01032 {
01033        int           i;
01034 
01035        assert( v != NULL );
01036 
01037        for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
01038               ch_free( v[ i ].word.bv_val );
01039        }
01040 
01041        ch_free( v );
01042 
01043        return 0;
01044 }
01045 
01046 int
01047 slap_verbmasks_append(
01048        slap_verbmasks       **vp,
01049        slap_mask_t   m,
01050        struct berval *v,
01051        slap_mask_t   *ignore )
01052 {
01053        int    i;
01054 
01055        if ( !m ) {
01056               return LDAP_OPERATIONS_ERROR;
01057        }
01058 
01059        for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
01060               if ( !(*vp)[ i ].mask ) continue;
01061 
01062               if ( ignore != NULL ) {
01063                      int    j;
01064 
01065                      for ( j = 0; ignore[ j ] != 0; j++ ) {
01066                             if ( (*vp)[ i ].mask == ignore[ j ] ) {
01067                                    goto check_next;
01068                             }
01069                      }
01070               }
01071 
01072               if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
01073                      if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
01074                             /* already set; ignore */
01075                             return LDAP_SUCCESS;
01076                      }
01077                      /* conflicts */
01078                      return LDAP_TYPE_OR_VALUE_EXISTS;
01079               }
01080 
01081               if ( m & (*vp)[ i ].mask ) {
01082                      /* conflicts */
01083                      return LDAP_CONSTRAINT_VIOLATION;
01084               }
01085 check_next:;
01086        }
01087 
01088        *vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
01089        ber_dupbv( &(*vp)[ i ].word, v );
01090        *((slap_mask_t *)&(*vp)[ i ].mask) = m;
01091        BER_BVZERO( &(*vp)[ i + 1 ].word );
01092 
01093        return LDAP_SUCCESS;
01094 }
01095 
01096 int
01097 enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
01098        int i;
01099 
01100        for (i=0; !BER_BVISNULL(&v[i].word); i++) {
01101               if ( m == v[i].mask ) {
01102                      if ( bv != NULL ) {
01103                             *bv = v[i].word;
01104                      }
01105                      return i;
01106               }
01107        }
01108        return -1;
01109 }
01110 
01111 /* register a new verbmask */
01112 static int
01113 slap_verbmask_register( slap_verbmasks *vm_, slap_verbmasks **vmp, struct berval *bv, int mask )
01114 {
01115        slap_verbmasks       *vm = *vmp;
01116        int           i;
01117 
01118        /* check for duplicate word */
01119        /* NOTE: we accept duplicate codes; the first occurrence will be used
01120         * when mapping from mask to verb */
01121        i = verb_to_mask( bv->bv_val, vm );
01122        if ( !BER_BVISNULL( &vm[ i ].word ) ) {
01123               return -1;
01124        }
01125 
01126        for ( i = 0; !BER_BVISNULL( &vm[ i ].word ); i++ )
01127               ;
01128 
01129        if ( vm == vm_ ) {
01130               /* first time: duplicate array */
01131               vm = ch_calloc( i + 2, sizeof( slap_verbmasks ) );
01132               for ( i = 0; !BER_BVISNULL( &vm_[ i ].word ); i++ )
01133               {
01134                      ber_dupbv( &vm[ i ].word, &vm_[ i ].word );
01135                      *((slap_mask_t*)&vm[ i ].mask) = vm_[ i ].mask;
01136               }
01137 
01138        } else {
01139               vm = ch_realloc( vm, (i + 2) * sizeof( slap_verbmasks ) );
01140        }
01141 
01142        ber_dupbv( &vm[ i ].word, bv );
01143        *((slap_mask_t*)&vm[ i ].mask) = mask;
01144 
01145        BER_BVZERO( &vm[ i+1 ].word );
01146 
01147        *vmp = vm;
01148 
01149        return i;
01150 }
01151 
01152 static slap_verbmasks slap_ldap_response_code_[] = {
01153        { BER_BVC("success"),                            LDAP_SUCCESS },
01154 
01155        { BER_BVC("operationsError"),                    LDAP_OPERATIONS_ERROR },
01156        { BER_BVC("protocolError"),               LDAP_PROTOCOL_ERROR },
01157        { BER_BVC("timelimitExceeded"),                  LDAP_TIMELIMIT_EXCEEDED },
01158        { BER_BVC("sizelimitExceeded"),                  LDAP_SIZELIMIT_EXCEEDED },
01159        { BER_BVC("compareFalse"),                LDAP_COMPARE_FALSE },
01160        { BER_BVC("compareTrue"),                 LDAP_COMPARE_TRUE },
01161 
01162        { BER_BVC("authMethodNotSupported"),             LDAP_AUTH_METHOD_NOT_SUPPORTED },
01163        { BER_BVC("strongAuthNotSupported"),             LDAP_STRONG_AUTH_NOT_SUPPORTED },
01164        { BER_BVC("strongAuthRequired"),          LDAP_STRONG_AUTH_REQUIRED },
01165        { BER_BVC("strongerAuthRequired"),        LDAP_STRONGER_AUTH_REQUIRED },
01166 #if 0 /* not LDAPv3 */
01167        { BER_BVC("partialResults"),                     LDAP_PARTIAL_RESULTS },
01168 #endif
01169 
01170        { BER_BVC("referral"),                           LDAP_REFERRAL },
01171        { BER_BVC("adminlimitExceeded"),          LDAP_ADMINLIMIT_EXCEEDED },
01172        { BER_BVC("unavailableCriticalExtension"),       LDAP_UNAVAILABLE_CRITICAL_EXTENSION },
01173        { BER_BVC("confidentialityRequired"),            LDAP_CONFIDENTIALITY_REQUIRED },
01174        { BER_BVC("saslBindInProgress"),          LDAP_SASL_BIND_IN_PROGRESS },
01175 
01176        { BER_BVC("noSuchAttribute"),                    LDAP_NO_SUCH_ATTRIBUTE },
01177        { BER_BVC("undefinedType"),               LDAP_UNDEFINED_TYPE },
01178        { BER_BVC("inappropriateMatching"),              LDAP_INAPPROPRIATE_MATCHING },
01179        { BER_BVC("constraintViolation"),         LDAP_CONSTRAINT_VIOLATION },
01180        { BER_BVC("typeOrValueExists"),                  LDAP_TYPE_OR_VALUE_EXISTS },
01181        { BER_BVC("invalidSyntax"),               LDAP_INVALID_SYNTAX },
01182 
01183        { BER_BVC("noSuchObject"),                LDAP_NO_SUCH_OBJECT },
01184        { BER_BVC("aliasProblem"),                LDAP_ALIAS_PROBLEM },
01185        { BER_BVC("invalidDnSyntax"),                    LDAP_INVALID_DN_SYNTAX },
01186 #if 0 /* not LDAPv3 */
01187        { BER_BVC("isLeaf"),                      LDAP_IS_LEAF },
01188 #endif
01189        { BER_BVC("aliasDerefProblem"),                  LDAP_ALIAS_DEREF_PROBLEM },
01190 
01191        { BER_BVC("proxyAuthzFailure"),                  LDAP_X_PROXY_AUTHZ_FAILURE },
01192        { BER_BVC("inappropriateAuth"),                  LDAP_INAPPROPRIATE_AUTH },
01193        { BER_BVC("invalidCredentials"),          LDAP_INVALID_CREDENTIALS },
01194        { BER_BVC("insufficientAccess"),          LDAP_INSUFFICIENT_ACCESS },
01195 
01196        { BER_BVC("busy"),                        LDAP_BUSY },
01197        { BER_BVC("unavailable"),                 LDAP_UNAVAILABLE },
01198        { BER_BVC("unwillingToPerform"),          LDAP_UNWILLING_TO_PERFORM },
01199        { BER_BVC("loopDetect"),                  LDAP_LOOP_DETECT },
01200 
01201        { BER_BVC("namingViolation"),                    LDAP_NAMING_VIOLATION },
01202        { BER_BVC("objectClassViolation"),        LDAP_OBJECT_CLASS_VIOLATION },
01203        { BER_BVC("notAllowedOnNonleaf"),         LDAP_NOT_ALLOWED_ON_NONLEAF },
01204        { BER_BVC("notAllowedOnRdn"),                    LDAP_NOT_ALLOWED_ON_RDN },
01205        { BER_BVC("alreadyExists"),               LDAP_ALREADY_EXISTS },
01206        { BER_BVC("noObjectClassMods"),                  LDAP_NO_OBJECT_CLASS_MODS },
01207        { BER_BVC("resultsTooLarge"),                    LDAP_RESULTS_TOO_LARGE },
01208        { BER_BVC("affectsMultipleDsas"),         LDAP_AFFECTS_MULTIPLE_DSAS },
01209 
01210        { BER_BVC("other"),                       LDAP_OTHER },
01211 
01212        /* extension-specific */
01213 
01214        { BER_BVC("cupResourcesExhausted"),              LDAP_CUP_RESOURCES_EXHAUSTED },
01215        { BER_BVC("cupSecurityViolation"),        LDAP_CUP_SECURITY_VIOLATION },
01216        { BER_BVC("cupInvalidData"),                     LDAP_CUP_INVALID_DATA },
01217        { BER_BVC("cupUnsupportedScheme"),        LDAP_CUP_UNSUPPORTED_SCHEME },
01218        { BER_BVC("cupReloadRequired"),                  LDAP_CUP_RELOAD_REQUIRED },
01219 
01220        { BER_BVC("cancelled"),                          LDAP_CANCELLED },
01221        { BER_BVC("noSuchOperation"),                    LDAP_NO_SUCH_OPERATION },
01222        { BER_BVC("tooLate"),                            LDAP_TOO_LATE },
01223        { BER_BVC("cannotCancel"),                LDAP_CANNOT_CANCEL },
01224 
01225        { BER_BVC("assertionFailed"),                    LDAP_ASSERTION_FAILED },
01226 
01227        { BER_BVC("proxiedAuthorizationDenied"),  LDAP_PROXIED_AUTHORIZATION_DENIED },
01228 
01229        { BER_BVC("syncRefreshRequired"),         LDAP_SYNC_REFRESH_REQUIRED },
01230 
01231        { BER_BVC("noOperation"),                 LDAP_X_NO_OPERATION },
01232 
01233        { BER_BVNULL,                      0 }
01234 };
01235 
01236 slap_verbmasks *slap_ldap_response_code = slap_ldap_response_code_;
01237 
01238 int
01239 slap_ldap_response_code_register( struct berval *bv, int err )
01240 {
01241        return slap_verbmask_register( slap_ldap_response_code_,
01242               &slap_ldap_response_code, bv, err );
01243 }
01244 
01245 #ifdef HAVE_TLS
01246 static slap_verbmasks tlskey[] = {
01247        { BER_BVC("no"),     SB_TLS_OFF },
01248        { BER_BVC("yes"),    SB_TLS_ON },
01249        { BER_BVC("critical"),      SB_TLS_CRITICAL },
01250        { BER_BVNULL, 0 }
01251 };
01252 
01253 static slap_verbmasks crlkeys[] = {
01254               { BER_BVC("none"),   LDAP_OPT_X_TLS_CRL_NONE },
01255               { BER_BVC("peer"),   LDAP_OPT_X_TLS_CRL_PEER },
01256               { BER_BVC("all"),    LDAP_OPT_X_TLS_CRL_ALL },
01257               { BER_BVNULL, 0 }
01258        };
01259 
01260 static slap_verbmasks vfykeys[] = {
01261               { BER_BVC("never"),  LDAP_OPT_X_TLS_NEVER },
01262               { BER_BVC("allow"),  LDAP_OPT_X_TLS_ALLOW },
01263               { BER_BVC("try"),    LDAP_OPT_X_TLS_TRY },
01264               { BER_BVC("demand"), LDAP_OPT_X_TLS_DEMAND },
01265               { BER_BVC("hard"),   LDAP_OPT_X_TLS_HARD },
01266               { BER_BVC("true"),   LDAP_OPT_X_TLS_HARD },
01267               { BER_BVNULL, 0 }
01268        };
01269 #endif
01270 
01271 static slap_verbmasks methkey[] = {
01272        { BER_BVC("none"),   LDAP_AUTH_NONE },
01273        { BER_BVC("simple"), LDAP_AUTH_SIMPLE },
01274 #ifdef HAVE_CYRUS_SASL
01275        { BER_BVC("sasl"),   LDAP_AUTH_SASL },
01276 #endif
01277        { BER_BVNULL, 0 }
01278 };
01279 
01280 static slap_verbmasks versionkey[] = {
01281        { BER_BVC("2"),             LDAP_VERSION2 },
01282        { BER_BVC("3"),             LDAP_VERSION3 },
01283        { BER_BVNULL, 0 }
01284 };
01285 
01286 static int 
01287 slap_keepalive_parse(
01288        struct berval *val,
01289        void *bc,
01290        slap_cf_aux_table *tab0,
01291        const char *tabmsg,
01292        int unparse )
01293 {
01294        if ( unparse ) {
01295               slap_keepalive *sk = (slap_keepalive *)bc;
01296               int rc = snprintf( val->bv_val, val->bv_len, "%d:%d:%d",
01297                      sk->sk_idle, sk->sk_probes, sk->sk_interval );
01298               if ( rc < 0 ) {
01299                      return -1;
01300               }
01301 
01302               if ( (unsigned)rc >= val->bv_len ) {
01303                      return -1;
01304               }
01305 
01306               val->bv_len = rc;
01307 
01308        } else {
01309               char *s = val->bv_val;
01310               char *next;
01311               slap_keepalive *sk = (slap_keepalive *)bc;
01312               slap_keepalive sk2;
01313 
01314               if ( s[0] == ':' ) {
01315                      sk2.sk_idle = 0;
01316                      s++;
01317                      
01318               } else {
01319                      sk2.sk_idle = strtol( s, &next, 10 );
01320                      if ( next == s || next[0] != ':' ) {
01321                             return -1;
01322                      }
01323 
01324                      if ( sk2.sk_idle < 0 ) {
01325                             return -1;
01326                      }
01327 
01328                      s = ++next;
01329               }
01330 
01331               if ( s[0] == ':' ) {
01332                      sk2.sk_probes = 0;
01333                      s++;
01334 
01335               } else {
01336                      sk2.sk_probes = strtol( s, &next, 10 );
01337                      if ( next == s || next[0] != ':' ) {
01338                             return -1;
01339                      }
01340 
01341                      if ( sk2.sk_probes < 0 ) {
01342                             return -1;
01343                      }
01344 
01345                      s = ++next;
01346               }
01347 
01348               if ( s == '\0' ) {
01349                      sk2.sk_interval = 0;
01350                      s++;
01351 
01352               } else {
01353                      sk2.sk_interval = strtol( s, &next, 10 );
01354                      if ( next == s || next[0] != '\0' ) {
01355                             return -1;
01356                      }
01357 
01358                      if ( sk2.sk_interval < 0 ) {
01359                             return -1;
01360                      }
01361               }
01362 
01363               *sk = sk2;
01364 
01365               ber_memfree( val->bv_val );
01366               BER_BVZERO( val );
01367        }
01368 
01369        return 0;
01370 }
01371 
01372 static int
01373 slap_sb_uri(
01374        struct berval *val,
01375        void *bcp,
01376        slap_cf_aux_table *tab0,
01377        const char *tabmsg,
01378        int unparse )
01379 {
01380        slap_bindconf *bc = bcp;
01381        if ( unparse ) {
01382               if ( bc->sb_uri.bv_len >= val->bv_len )
01383                      return -1;
01384               val->bv_len = bc->sb_uri.bv_len;
01385               AC_MEMCPY( val->bv_val, bc->sb_uri.bv_val, val->bv_len );
01386        } else {
01387               bc->sb_uri = *val;
01388 #ifdef HAVE_TLS
01389               if ( ldap_is_ldaps_url( val->bv_val ))
01390                      bc->sb_tls_do_init = 1;
01391 #endif
01392        }
01393        return 0;
01394 }
01395 
01396 static slap_cf_aux_table bindkey[] = {
01397        { BER_BVC("uri="), 0, 'x', 1, slap_sb_uri },
01398        { BER_BVC("version="), offsetof(slap_bindconf, sb_version), 'i', 0, versionkey },
01399        { BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'i', 0, methkey },
01400        { BER_BVC("timeout="), offsetof(slap_bindconf, sb_timeout_api), 'i', 0, NULL },
01401        { BER_BVC("network-timeout="), offsetof(slap_bindconf, sb_timeout_net), 'i', 0, NULL },
01402        { BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, (slap_verbmasks *)dnNormalize },
01403        { BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
01404        { BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
01405        { BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
01406        { BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
01407        { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 1, NULL },
01408        { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, (slap_verbmasks *)authzNormalize },
01409        { BER_BVC("keepalive="), offsetof(slap_bindconf, sb_keepalive), 'x', 0, (slap_verbmasks *)slap_keepalive_parse },
01410 #ifdef HAVE_TLS
01411        /* NOTE: replace "13" with the actual index
01412         * of the first TLS-related line */
01413 #define aux_TLS (bindkey+13)       /* beginning of TLS keywords */
01414 
01415        { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'i', 0, tlskey },
01416        { BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL },
01417        { BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL },
01418        { BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL },
01419        { BER_BVC("tls_cacertdir="), offsetof(slap_bindconf, sb_tls_cacertdir), 's', 1, NULL },
01420        { BER_BVC("tls_reqcert="), offsetof(slap_bindconf, sb_tls_reqcert), 's', 0, NULL },
01421        { BER_BVC("tls_cipher_suite="), offsetof(slap_bindconf, sb_tls_cipher_suite), 's', 0, NULL },
01422        { BER_BVC("tls_protocol_min="), offsetof(slap_bindconf, sb_tls_protocol_min), 's', 0, NULL },
01423 #ifdef HAVE_OPENSSL_CRL
01424        { BER_BVC("tls_crlcheck="), offsetof(slap_bindconf, sb_tls_crlcheck), 's', 0, NULL },
01425 #endif
01426 #endif
01427        { BER_BVNULL, 0, 0, 0, NULL }
01428 };
01429 
01430 /*
01431  * 's':       char *
01432  * 'b':       struct berval; if !NULL, normalize using ((slap_mr_normalize_func *)aux)
01433  * 'i':       int; if !NULL, compute using ((slap_verbmasks *)aux)
01434  * 'u':       unsigned
01435  * 'I':       long
01436  * 'U':       unsigned long
01437  */
01438 
01439 int
01440 slap_cf_aux_table_parse( const char *word, void *dst, slap_cf_aux_table *tab0, LDAP_CONST char *tabmsg )
01441 {
01442        int rc = SLAP_CONF_UNKNOWN;
01443        slap_cf_aux_table *tab;
01444 
01445        for ( tab = tab0; !BER_BVISNULL( &tab->key ); tab++ ) {
01446               if ( !strncasecmp( word, tab->key.bv_val, tab->key.bv_len ) ) {
01447                      char **cptr;
01448                      int *iptr, j;
01449                      unsigned *uptr;
01450                      long *lptr;
01451                      unsigned long *ulptr;
01452                      struct berval *bptr;
01453                      const char *val = word + tab->key.bv_len;
01454 
01455                      switch ( tab->type ) {
01456                      case 's':
01457                             cptr = (char **)((char *)dst + tab->off);
01458                             *cptr = ch_strdup( val );
01459                             rc = 0;
01460                             break;
01461 
01462                      case 'b':
01463                             bptr = (struct berval *)((char *)dst + tab->off);
01464                             if ( tab->aux != NULL ) {
01465                                    struct berval dn;
01466                                    slap_mr_normalize_func *normalize = (slap_mr_normalize_func *)tab->aux;
01467 
01468                                    ber_str2bv( val, 0, 0, &dn );
01469                                    rc = normalize( 0, NULL, NULL, &dn, bptr, NULL );
01470 
01471                             } else {
01472                                    ber_str2bv( val, 0, 1, bptr );
01473                                    rc = 0;
01474                             }
01475                             break;
01476 
01477                      case 'i':
01478                             iptr = (int *)((char *)dst + tab->off);
01479 
01480                             if ( tab->aux != NULL ) {
01481                                    slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
01482 
01483                                    assert( aux != NULL );
01484 
01485                                    rc = 1;
01486                                    for ( j = 0; !BER_BVISNULL( &aux[j].word ); j++ ) {
01487                                           if ( !strcasecmp( val, aux[j].word.bv_val ) ) {
01488                                                  *iptr = aux[j].mask;
01489                                                  rc = 0;
01490                                                  break;
01491                                           }
01492                                    }
01493 
01494                             } else {
01495                                    rc = lutil_atoix( iptr, val, 0 );
01496                             }
01497                             break;
01498 
01499                      case 'u':
01500                             uptr = (unsigned *)((char *)dst + tab->off);
01501 
01502                             rc = lutil_atoux( uptr, val, 0 );
01503                             break;
01504 
01505                      case 'I':
01506                             lptr = (long *)((char *)dst + tab->off);
01507 
01508                             rc = lutil_atolx( lptr, val, 0 );
01509                             break;
01510 
01511                      case 'U':
01512                             ulptr = (unsigned long *)((char *)dst + tab->off);
01513 
01514                             rc = lutil_atoulx( ulptr, val, 0 );
01515                             break;
01516 
01517                      case 'x':
01518                             if ( tab->aux != NULL ) {
01519                                    struct berval value;
01520                                    slap_cf_aux_table_parse_x *func = (slap_cf_aux_table_parse_x *)tab->aux;
01521 
01522                                    ber_str2bv( val, 0, 1, &value );
01523 
01524                                    rc = func( &value, (void *)((char *)dst + tab->off), tab, tabmsg, 0 );
01525 
01526                             } else {
01527                                    rc = 1;
01528                             }
01529                             break;
01530                      }
01531 
01532                      if ( rc ) {
01533                             Debug( LDAP_DEBUG_ANY, "invalid %s value %s\n",
01534                                    tabmsg, word, 0 );
01535                      }
01536                      
01537                      return rc;
01538               }
01539        }
01540 
01541        return rc;
01542 }
01543 
01544 int
01545 slap_cf_aux_table_unparse( void *src, struct berval *bv, slap_cf_aux_table *tab0 )
01546 {
01547        char buf[AC_LINE_MAX], *ptr;
01548        slap_cf_aux_table *tab;
01549        struct berval tmp;
01550 
01551        ptr = buf;
01552        for (tab = tab0; !BER_BVISNULL(&tab->key); tab++ ) {
01553               char **cptr;
01554               int *iptr, i;
01555               unsigned *uptr;
01556               long *lptr;
01557               unsigned long *ulptr;
01558               struct berval *bptr;
01559 
01560               cptr = (char **)((char *)src + tab->off);
01561 
01562               switch ( tab->type ) {
01563               case 'b':
01564                      bptr = (struct berval *)((char *)src + tab->off);
01565                      cptr = &bptr->bv_val;
01566 
01567               case 's':
01568                      if ( *cptr ) {
01569                             *ptr++ = ' ';
01570                             ptr = lutil_strcopy( ptr, tab->key.bv_val );
01571                             if ( tab->quote ) *ptr++ = '"';
01572                             ptr = lutil_strcopy( ptr, *cptr );
01573                             if ( tab->quote ) *ptr++ = '"';
01574                      }
01575                      break;
01576 
01577               case 'i':
01578                      iptr = (int *)((char *)src + tab->off);
01579 
01580                      if ( tab->aux != NULL ) {
01581                             slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
01582 
01583                             for ( i = 0; !BER_BVISNULL( &aux[i].word ); i++ ) {
01584                                    if ( *iptr == aux[i].mask ) {
01585                                           *ptr++ = ' ';
01586                                           ptr = lutil_strcopy( ptr, tab->key.bv_val );
01587                                           ptr = lutil_strcopy( ptr, aux[i].word.bv_val );
01588                                           break;
01589                                    }
01590                             }
01591 
01592                      } else {
01593                             *ptr++ = ' ';
01594                             ptr = lutil_strcopy( ptr, tab->key.bv_val );
01595                             ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%d", *iptr );
01596                      }
01597                      break;
01598 
01599               case 'u':
01600                      uptr = (unsigned *)((char *)src + tab->off);
01601                      *ptr++ = ' ';
01602                      ptr = lutil_strcopy( ptr, tab->key.bv_val );
01603                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%u", *uptr );
01604                      break;
01605 
01606               case 'I':
01607                      lptr = (long *)((char *)src + tab->off);
01608                      *ptr++ = ' ';
01609                      ptr = lutil_strcopy( ptr, tab->key.bv_val );
01610                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%ld", *lptr );
01611                      break;
01612 
01613               case 'U':
01614                      ulptr = (unsigned long *)((char *)src + tab->off);
01615                      *ptr++ = ' ';
01616                      ptr = lutil_strcopy( ptr, tab->key.bv_val );
01617                      ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%lu", *ulptr );
01618                      break;
01619 
01620               case 'x':
01621                      {
01622                             char *saveptr=ptr;
01623                             *ptr++ = ' ';
01624                             ptr = lutil_strcopy( ptr, tab->key.bv_val );
01625                             if ( tab->quote ) *ptr++ = '"';
01626                             if ( tab->aux != NULL ) {
01627                                    struct berval value;
01628                                    slap_cf_aux_table_parse_x *func = (slap_cf_aux_table_parse_x *)tab->aux;
01629                                    int rc;
01630 
01631                                    value.bv_val = ptr;
01632                                    value.bv_len = buf + sizeof( buf ) - ptr;
01633 
01634                                    rc = func( &value, (void *)((char *)src + tab->off), tab, "(unparse)", 1 );
01635                                    if ( rc == 0 ) {
01636                                           if (value.bv_len) {
01637                                                  ptr += value.bv_len;
01638                                           } else {
01639                                                  ptr = saveptr;
01640                                                  break;
01641                                           }
01642                                    }
01643                             }
01644                             if ( tab->quote ) *ptr++ = '"';
01645                      }
01646                      break;
01647 
01648               default:
01649                      assert( 0 );
01650               }
01651        }
01652        tmp.bv_val = buf;
01653        tmp.bv_len = ptr - buf;
01654        ber_dupbv( bv, &tmp );
01655        return 0;
01656 }
01657 
01658 int
01659 slap_tls_get_config( LDAP *ld, int opt, char **val )
01660 {
01661 #ifdef HAVE_TLS
01662        slap_verbmasks *keys;
01663        int i, ival;
01664 
01665        *val = NULL;
01666        switch( opt ) {
01667        case LDAP_OPT_X_TLS_CRLCHECK:
01668               keys = crlkeys;
01669               break;
01670        case LDAP_OPT_X_TLS_REQUIRE_CERT:
01671               keys = vfykeys;
01672               break;
01673        case LDAP_OPT_X_TLS_PROTOCOL_MIN: {
01674               char buf[8];
01675               ldap_pvt_tls_get_option( ld, opt, &ival );
01676               snprintf( buf, sizeof( buf ), "%d.%d",
01677                      ( ival >> 8 ) & 0xff, ival & 0xff );
01678               *val = ch_strdup( buf );
01679               return 0;
01680               }
01681        default:
01682               return -1;
01683        }
01684        ldap_pvt_tls_get_option( ld, opt, &ival );
01685        for (i=0; !BER_BVISNULL(&keys[i].word); i++) {
01686               if (keys[i].mask == ival) {
01687                      *val = ch_strdup( keys[i].word.bv_val );
01688                      return 0;
01689               }
01690        }
01691 #endif
01692        return -1;
01693 }
01694 
01695 int
01696 bindconf_tls_parse( const char *word, slap_bindconf *bc )
01697 {
01698 #ifdef HAVE_TLS
01699        if ( slap_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) {
01700               bc->sb_tls_do_init = 1;
01701               return 0;
01702        }
01703 #endif
01704        return -1;
01705 }
01706 
01707 int
01708 bindconf_tls_unparse( slap_bindconf *bc, struct berval *bv )
01709 {
01710 #ifdef HAVE_TLS
01711        return slap_cf_aux_table_unparse( bc, bv, aux_TLS );
01712 #endif
01713        return -1;
01714 }
01715 
01716 int
01717 bindconf_parse( const char *word, slap_bindconf *bc )
01718 {
01719 #ifdef HAVE_TLS
01720        /* Detect TLS config changes explicitly */
01721        if ( bindconf_tls_parse( word, bc ) == 0 ) {
01722               return 0;
01723        }
01724 #endif
01725        return slap_cf_aux_table_parse( word, bc, bindkey, "bind config" );
01726 }
01727 
01728 int
01729 bindconf_unparse( slap_bindconf *bc, struct berval *bv )
01730 {
01731        return slap_cf_aux_table_unparse( bc, bv, bindkey );
01732 }
01733 
01734 void bindconf_free( slap_bindconf *bc ) {
01735        if ( !BER_BVISNULL( &bc->sb_uri ) ) {
01736               ch_free( bc->sb_uri.bv_val );
01737               BER_BVZERO( &bc->sb_uri );
01738        }
01739        if ( !BER_BVISNULL( &bc->sb_binddn ) ) {
01740               ch_free( bc->sb_binddn.bv_val );
01741               BER_BVZERO( &bc->sb_binddn );
01742        }
01743        if ( !BER_BVISNULL( &bc->sb_cred ) ) {
01744               ch_free( bc->sb_cred.bv_val );
01745               BER_BVZERO( &bc->sb_cred );
01746        }
01747        if ( !BER_BVISNULL( &bc->sb_saslmech ) ) {
01748               ch_free( bc->sb_saslmech.bv_val );
01749               BER_BVZERO( &bc->sb_saslmech );
01750        }
01751        if ( bc->sb_secprops ) {
01752               ch_free( bc->sb_secprops );
01753               bc->sb_secprops = NULL;
01754        }
01755        if ( !BER_BVISNULL( &bc->sb_realm ) ) {
01756               ch_free( bc->sb_realm.bv_val );
01757               BER_BVZERO( &bc->sb_realm );
01758        }
01759        if ( !BER_BVISNULL( &bc->sb_authcId ) ) {
01760               ch_free( bc->sb_authcId.bv_val );
01761               BER_BVZERO( &bc->sb_authcId );
01762        }
01763        if ( !BER_BVISNULL( &bc->sb_authzId ) ) {
01764               ch_free( bc->sb_authzId.bv_val );
01765               BER_BVZERO( &bc->sb_authzId );
01766        }
01767 #ifdef HAVE_TLS
01768        if ( bc->sb_tls_cert ) {
01769               ch_free( bc->sb_tls_cert );
01770               bc->sb_tls_cert = NULL;
01771        }
01772        if ( bc->sb_tls_key ) {
01773               ch_free( bc->sb_tls_key );
01774               bc->sb_tls_key = NULL;
01775        }
01776        if ( bc->sb_tls_cacert ) {
01777               ch_free( bc->sb_tls_cacert );
01778               bc->sb_tls_cacert = NULL;
01779        }
01780        if ( bc->sb_tls_cacertdir ) {
01781               ch_free( bc->sb_tls_cacertdir );
01782               bc->sb_tls_cacertdir = NULL;
01783        }
01784        if ( bc->sb_tls_reqcert ) {
01785               ch_free( bc->sb_tls_reqcert );
01786               bc->sb_tls_reqcert = NULL;
01787        }
01788        if ( bc->sb_tls_cipher_suite ) {
01789               ch_free( bc->sb_tls_cipher_suite );
01790               bc->sb_tls_cipher_suite = NULL;
01791        }
01792        if ( bc->sb_tls_protocol_min ) {
01793               ch_free( bc->sb_tls_protocol_min );
01794               bc->sb_tls_protocol_min = NULL;
01795        }
01796 #ifdef HAVE_OPENSSL_CRL
01797        if ( bc->sb_tls_crlcheck ) {
01798               ch_free( bc->sb_tls_crlcheck );
01799               bc->sb_tls_crlcheck = NULL;
01800        }
01801 #endif
01802        if ( bc->sb_tls_ctx ) {
01803               ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
01804               bc->sb_tls_ctx = NULL;
01805        }
01806 #endif
01807 }
01808 
01809 void
01810 bindconf_tls_defaults( slap_bindconf *bc )
01811 {
01812 #ifdef HAVE_TLS
01813        if ( bc->sb_tls_do_init ) {
01814               if ( !bc->sb_tls_cacert )
01815                      ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CACERTFILE,
01816                             &bc->sb_tls_cacert );
01817               if ( !bc->sb_tls_cacertdir )
01818                      ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CACERTDIR,
01819                             &bc->sb_tls_cacertdir );
01820               if ( !bc->sb_tls_cert )
01821                      ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CERTFILE,
01822                             &bc->sb_tls_cert );
01823               if ( !bc->sb_tls_key )
01824                      ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_KEYFILE,
01825                             &bc->sb_tls_key );
01826               if ( !bc->sb_tls_cipher_suite )
01827                      ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CIPHER_SUITE,
01828                             &bc->sb_tls_cipher_suite );
01829               if ( !bc->sb_tls_reqcert )
01830                      bc->sb_tls_reqcert = ch_strdup("demand");
01831 #ifdef HAVE_OPENSSL_CRL
01832               if ( !bc->sb_tls_crlcheck )
01833                      slap_tls_get_config( slap_tls_ld, LDAP_OPT_X_TLS_CRLCHECK,
01834                             &bc->sb_tls_crlcheck );
01835 #endif
01836        }
01837 #endif
01838 }
01839 
01840 #ifdef HAVE_TLS
01841 static struct {
01842        const char *key;
01843        size_t offset;
01844        int opt;
01845 } bindtlsopts[] = {
01846        { "tls_cert", offsetof(slap_bindconf, sb_tls_cert), LDAP_OPT_X_TLS_CERTFILE },
01847        { "tls_key", offsetof(slap_bindconf, sb_tls_key), LDAP_OPT_X_TLS_KEYFILE },
01848        { "tls_cacert", offsetof(slap_bindconf, sb_tls_cacert), LDAP_OPT_X_TLS_CACERTFILE },
01849        { "tls_cacertdir", offsetof(slap_bindconf, sb_tls_cacertdir), LDAP_OPT_X_TLS_CACERTDIR },
01850        { "tls_cipher_suite", offsetof(slap_bindconf, sb_tls_cipher_suite), LDAP_OPT_X_TLS_CIPHER_SUITE },
01851        { "tls_protocol_min", offsetof(slap_bindconf, sb_tls_protocol_min), LDAP_OPT_X_TLS_PROTOCOL_MIN },
01852        {0, 0}
01853 };
01854 
01855 int bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
01856 {
01857        int i, rc, newctx = 0, res = 0;
01858        char *ptr = (char *)bc, **word;
01859 
01860        bc->sb_tls_do_init = 0;
01861 
01862        for (i=0; bindtlsopts[i].opt; i++) {
01863               word = (char **)(ptr + bindtlsopts[i].offset);
01864               if ( *word ) {
01865                      rc = ldap_set_option( ld, bindtlsopts[i].opt, *word );
01866                      if ( rc ) {
01867                             Debug( LDAP_DEBUG_ANY,
01868                                    "bindconf_tls_set: failed to set %s to %s\n",
01869                                           bindtlsopts[i].key, *word, 0 );
01870                             res = -1;
01871                      } else
01872                             newctx = 1;
01873               }
01874        }
01875        if ( bc->sb_tls_reqcert ) {
01876               rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_REQUIRE_CERT,
01877                      bc->sb_tls_reqcert );
01878               if ( rc ) {
01879                      Debug( LDAP_DEBUG_ANY,
01880                             "bindconf_tls_set: failed to set tls_reqcert to %s\n",
01881                                    bc->sb_tls_reqcert, 0, 0 );
01882                      res = -1;
01883               } else
01884                      newctx = 1;
01885        }
01886        if ( bc->sb_tls_protocol_min ) {
01887               rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_PROTOCOL_MIN,
01888                      bc->sb_tls_protocol_min );
01889               if ( rc ) {
01890                      Debug( LDAP_DEBUG_ANY,
01891                             "bindconf_tls_set: failed to set tls_protocol_min to %s\n",
01892                                    bc->sb_tls_protocol_min, 0, 0 );
01893                      res = -1;
01894               } else
01895                      newctx = 1;
01896        }
01897 #ifdef HAVE_OPENSSL_CRL
01898        if ( bc->sb_tls_crlcheck ) {
01899               rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_CRLCHECK,
01900                      bc->sb_tls_crlcheck );
01901               if ( rc ) {
01902                      Debug( LDAP_DEBUG_ANY,
01903                             "bindconf_tls_set: failed to set tls_crlcheck to %s\n",
01904                                    bc->sb_tls_crlcheck, 0, 0 );
01905                      res = -1;
01906               } else
01907                      newctx = 1;
01908        }
01909 #endif
01910        if ( newctx ) {
01911               int opt = 0;
01912 
01913               if ( bc->sb_tls_ctx ) {
01914                      ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
01915                      bc->sb_tls_ctx = NULL;
01916               }
01917               rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
01918               if ( rc )
01919                      res = rc;
01920               else
01921                      ldap_get_option( ld, LDAP_OPT_X_TLS_CTX, &bc->sb_tls_ctx );
01922        }
01923        
01924        return res;
01925 }
01926 #endif
01927 
01928 /*
01929  * connect to a client using the bindconf data
01930  * note: should move "version" into bindconf...
01931  */
01932 int
01933 slap_client_connect( LDAP **ldp, slap_bindconf *sb )
01934 {
01935        LDAP          *ld = NULL;
01936        int           rc;
01937        struct timeval tv;
01938 
01939        /* Init connection to master */
01940        rc = ldap_initialize( &ld, sb->sb_uri.bv_val );
01941        if ( rc != LDAP_SUCCESS ) {
01942               Debug( LDAP_DEBUG_ANY,
01943                      "slap_client_connect: "
01944                      "ldap_initialize(%s) failed (%d)\n",
01945                      sb->sb_uri.bv_val, rc, 0 );
01946               return rc;
01947        }
01948 
01949        if ( sb->sb_version != 0 ) {
01950               ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
01951                      (const void *)&sb->sb_version );
01952        }
01953 
01954        if ( sb->sb_timeout_api ) {
01955               tv.tv_sec = sb->sb_timeout_api;
01956               tv.tv_usec = 0;
01957               ldap_set_option( ld, LDAP_OPT_TIMEOUT, &tv );
01958        }
01959 
01960        if ( sb->sb_timeout_net ) {
01961               tv.tv_sec = sb->sb_timeout_net;
01962               tv.tv_usec = 0;
01963               ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, &tv );
01964        }
01965 
01966        if ( sb->sb_keepalive.sk_idle ) {
01967               ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_IDLE, &sb->sb_keepalive.sk_idle );
01968        }
01969 
01970        if ( sb->sb_keepalive.sk_probes ) {
01971               ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_PROBES, &sb->sb_keepalive.sk_probes );
01972        }
01973 
01974        if ( sb->sb_keepalive.sk_interval ) {
01975               ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_INTERVAL, &sb->sb_keepalive.sk_interval );
01976        }
01977 
01978 #ifdef HAVE_TLS
01979        if ( sb->sb_tls_do_init ) {
01980               rc = bindconf_tls_set( sb, ld );
01981 
01982        } else if ( sb->sb_tls_ctx ) {
01983               rc = ldap_set_option( ld, LDAP_OPT_X_TLS_CTX,
01984                      sb->sb_tls_ctx );
01985        }
01986 
01987        if ( rc ) {
01988               Debug( LDAP_DEBUG_ANY,
01989                      "slap_client_connect: "
01990                      "URI=%s TLS context initialization failed (%d)\n",
01991                      sb->sb_uri.bv_val, rc, 0 );
01992               return rc;
01993        }
01994 #endif
01995 
01996        /* Bind */
01997        if ( sb->sb_tls ) {
01998               rc = ldap_start_tls_s( ld, NULL, NULL );
01999               if ( rc != LDAP_SUCCESS ) {
02000                      Debug( LDAP_DEBUG_ANY,
02001                             "slap_client_connect: URI=%s "
02002                             "%s, ldap_start_tls failed (%d)\n",
02003                             sb->sb_uri.bv_val,
02004                             sb->sb_tls == SB_TLS_CRITICAL ?
02005                                    "Error" : "Warning",
02006                             rc );
02007                      if ( sb->sb_tls == SB_TLS_CRITICAL ) {
02008                             goto done;
02009                      }
02010               }
02011        }
02012 
02013        if ( sb->sb_method == LDAP_AUTH_SASL ) {
02014 #ifdef HAVE_CYRUS_SASL
02015               void *defaults;
02016 
02017               if ( sb->sb_secprops != NULL ) {
02018                      rc = ldap_set_option( ld,
02019                             LDAP_OPT_X_SASL_SECPROPS, sb->sb_secprops);
02020 
02021                      if( rc != LDAP_OPT_SUCCESS ) {
02022                             Debug( LDAP_DEBUG_ANY,
02023                                    "slap_client_connect: "
02024                                    "error, ldap_set_option "
02025                                    "(%s,SECPROPS,\"%s\") failed!\n",
02026                                    sb->sb_uri.bv_val, sb->sb_secprops, 0 );
02027                             goto done;
02028                      }
02029               }
02030 
02031               defaults = lutil_sasl_defaults( ld,
02032                      sb->sb_saslmech.bv_val,
02033                      sb->sb_realm.bv_val,
02034                      sb->sb_authcId.bv_val,
02035                      sb->sb_cred.bv_val,
02036                      sb->sb_authzId.bv_val );
02037               if ( defaults == NULL ) {
02038                      rc = LDAP_OTHER;
02039                      goto done;
02040               }
02041 
02042               rc = ldap_sasl_interactive_bind_s( ld,
02043                             sb->sb_binddn.bv_val,
02044                             sb->sb_saslmech.bv_val,
02045                             NULL, NULL,
02046                             LDAP_SASL_QUIET,
02047                             lutil_sasl_interact,
02048                             defaults );
02049 
02050               lutil_sasl_freedefs( defaults );
02051 
02052               /* FIXME: different error behaviors according to
02053                *     1) return code
02054                *     2) on err policy : exit, retry, backoff ...
02055                */
02056               if ( rc != LDAP_SUCCESS ) {
02057                      static struct berval bv_GSSAPI = BER_BVC( "GSSAPI" );
02058 
02059                      Debug( LDAP_DEBUG_ANY, "slap_client_connect: URI=%s "
02060                             "ldap_sasl_interactive_bind_s failed (%d)\n",
02061                             sb->sb_uri.bv_val, rc, 0 );
02062 
02063                      /* FIXME (see above comment) */
02064                      /* if Kerberos credentials cache is not active, retry */
02065                      if ( ber_bvcmp( &sb->sb_saslmech, &bv_GSSAPI ) == 0 &&
02066                             rc == LDAP_LOCAL_ERROR )
02067                      {
02068                             rc = LDAP_SERVER_DOWN;
02069                      }
02070 
02071                      goto done;
02072               }
02073 #else /* HAVE_CYRUS_SASL */
02074               /* Should never get here, we trapped this at config time */
02075               assert(0);
02076               Debug( LDAP_DEBUG_SYNC, "not compiled with SASL support\n", 0, 0, 0 );
02077               rc = LDAP_OTHER;
02078               goto done;
02079 #endif
02080 
02081        } else if ( sb->sb_method == LDAP_AUTH_SIMPLE ) {
02082               rc = ldap_sasl_bind_s( ld,
02083                      sb->sb_binddn.bv_val, LDAP_SASL_SIMPLE,
02084                      &sb->sb_cred, NULL, NULL, NULL );
02085               if ( rc != LDAP_SUCCESS ) {
02086                      Debug( LDAP_DEBUG_ANY, "slap_client_connect: "
02087                             "URI=%s DN=\"%s\" "
02088                             "ldap_sasl_bind_s failed (%d)\n",
02089                             sb->sb_uri.bv_val, sb->sb_binddn.bv_val, rc );
02090                      goto done;
02091               }
02092        }
02093 
02094 done:;
02095        if ( rc ) {
02096               if ( ld ) {
02097                      ldap_unbind_ext( ld, NULL, NULL );
02098                      *ldp = NULL;
02099               }
02100 
02101        } else {
02102               *ldp = ld;
02103        }
02104 
02105        return rc;
02106 }
02107 
02108 /* -------------------------------------- */
02109 
02110 
02111 static char *
02112 strtok_quote( char *line, char *sep, char **quote_ptr )
02113 {
02114        int           inquote;
02115        char          *tmp;
02116        static char   *next;
02117 
02118        *quote_ptr = NULL;
02119        if ( line != NULL ) {
02120               next = line;
02121        }
02122        while ( *next && strchr( sep, *next ) ) {
02123               next++;
02124        }
02125 
02126        if ( *next == '\0' ) {
02127               next = NULL;
02128               return( NULL );
02129        }
02130        tmp = next;
02131 
02132        for ( inquote = 0; *next; ) {
02133               switch ( *next ) {
02134               case '"':
02135                      if ( inquote ) {
02136                             inquote = 0;
02137                      } else {
02138                             inquote = 1;
02139                      }
02140                      AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
02141                      break;
02142 
02143               case '\\':
02144                      if ( next[1] )
02145                             AC_MEMCPY( next,
02146                                        next + 1, strlen( next + 1 ) + 1 );
02147                      next++;              /* dont parse the escaped character */
02148                      break;
02149 
02150               default:
02151                      if ( ! inquote ) {
02152                             if ( strchr( sep, *next ) != NULL ) {
02153                                    *quote_ptr = next;
02154                                    *next++ = '\0';
02155                                    return( tmp );
02156                             }
02157                      }
02158                      next++;
02159                      break;
02160               }
02161        }
02162 
02163        return( tmp );
02164 }
02165 
02166 static char   buf[AC_LINE_MAX];
02167 static char   *line;
02168 static size_t lmax, lcur;
02169 
02170 #define CATLINE( buf ) \
02171        do { \
02172               size_t len = strlen( buf ); \
02173               while ( lcur + len + 1 > lmax ) { \
02174                      lmax += AC_LINE_MAX; \
02175                      line = (char *) ch_realloc( line, lmax ); \
02176               } \
02177               strcpy( line + lcur, buf ); \
02178               lcur += len; \
02179        } while( 0 )
02180 
02181 static void
02182 fp_getline_init(ConfigArgs *c) {
02183        c->lineno = -1;
02184        buf[0] = '\0';
02185 }
02186 
02187 static int
02188 fp_getline( FILE *fp, ConfigArgs *c )
02189 {
02190        char   *p;
02191 
02192        lcur = 0;
02193        CATLINE(buf);
02194        c->lineno++;
02195 
02196        /* avoid stack of bufs */
02197        if ( strncasecmp( line, "include", STRLENOF( "include" ) ) == 0 ) {
02198               buf[0] = '\0';
02199               c->line = line;
02200               return(1);
02201        }
02202 
02203        while ( fgets( buf, sizeof( buf ), fp ) ) {
02204               p = strchr( buf, '\n' );
02205               if ( p ) {
02206                      if ( p > buf && p[-1] == '\r' ) {
02207                             --p;
02208                      }
02209                      *p = '\0';
02210               }
02211               /* XXX ugly */
02212               c->line = line;
02213               if ( line[0]
02214                             && ( p = line + strlen( line ) - 1 )[0] == '\\'
02215                             && p[-1] != '\\' )
02216               {
02217                      p[0] = '\0';
02218                      lcur--;
02219                      
02220               } else {
02221                      if ( !isspace( (unsigned char)buf[0] ) ) {
02222                             return(1);
02223                      }
02224                      buf[0] = ' ';
02225               }
02226               CATLINE(buf);
02227               c->lineno++;
02228        }
02229 
02230        buf[0] = '\0';
02231        c->line = line;
02232        return(line[0] ? 1 : 0);
02233 }
02234 
02235 int
02236 config_fp_parse_line(ConfigArgs *c)
02237 {
02238        char *token;
02239        static char *const hide[] = {
02240               "rootpw", "replica", "syncrepl",  /* in slapd */
02241               "acl-bind", "acl-method", "idassert-bind",  /* in back-ldap */
02242               "acl-passwd", "bindpw",  /* in back-<ldap/meta> */
02243               "pseudorootpw",  /* in back-meta */
02244               "dbpasswd",  /* in back-sql */
02245               NULL
02246        };
02247        char *quote_ptr;
02248        int i = (int)(sizeof(hide)/sizeof(hide[0])) - 1;
02249 
02250        c->tline = ch_strdup(c->line);
02251        token = strtok_quote(c->tline, " \t", &quote_ptr);
02252 
02253        if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
02254        if(quote_ptr) *quote_ptr = ' ';
02255        Debug(LDAP_DEBUG_CONFIG, "line %d (%s%s)\n", c->lineno,
02256               hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "");
02257        if(quote_ptr) *quote_ptr = '\0';
02258 
02259        for(;; token = strtok_quote(NULL, " \t", &quote_ptr)) {
02260               if(c->argc >= c->argv_size) {
02261                      char **tmp;
02262                      tmp = ch_realloc(c->argv, (c->argv_size + ARGS_STEP) * sizeof(*c->argv));
02263                      if(!tmp) {
02264                             Debug(LDAP_DEBUG_ANY, "line %d: out of memory\n", c->lineno, 0, 0);
02265                             return -1;
02266                      }
02267                      c->argv = tmp;
02268                      c->argv_size += ARGS_STEP;
02269               }
02270               if(token == NULL)
02271                      break;
02272               c->argv[c->argc++] = token;
02273        }
02274        c->argv[c->argc] = NULL;
02275        return(0);
02276 }
02277 
02278 void
02279 config_destroy( )
02280 {
02281        ucdata_unload( UCDATA_ALL );
02282        if ( frontendDB ) {
02283               /* NOTE: in case of early exit, frontendDB can be NULL */
02284               if ( frontendDB->be_schemandn.bv_val )
02285                      free( frontendDB->be_schemandn.bv_val );
02286               if ( frontendDB->be_schemadn.bv_val )
02287                      free( frontendDB->be_schemadn.bv_val );
02288               if ( frontendDB->be_acl )
02289                      acl_destroy( frontendDB->be_acl );
02290        }
02291        free( line );
02292        if ( slapd_args_file )
02293               free ( slapd_args_file );
02294        if ( slapd_pid_file )
02295               free ( slapd_pid_file );
02296        if ( default_passwd_hash )
02297               ldap_charray_free( default_passwd_hash );
02298 }
02299 
02300 char **
02301 slap_str2clist( char ***out, char *in, const char *brkstr )
02302 {
02303        char   *str;
02304        char   *s;
02305        char   *lasts;
02306        int    i, j;
02307        char   **new;
02308 
02309        /* find last element in list */
02310        for (i = 0; *out && (*out)[i]; i++);
02311 
02312        /* protect the input string from strtok */
02313        str = ch_strdup( in );
02314 
02315        if ( *str == '\0' ) {
02316               free( str );
02317               return( *out );
02318        }
02319 
02320        /* Count words in string */
02321        j=1;
02322        for ( s = str; *s; s++ ) {
02323               if ( strchr( brkstr, *s ) != NULL ) {
02324                      j++;
02325               }
02326        }
02327 
02328        *out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
02329        new = *out + i;
02330        for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
02331               s != NULL;
02332               s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
02333        {
02334               *new = ch_strdup( s );
02335               new++;
02336        }
02337 
02338        *new = NULL;
02339        free( str );
02340        return( *out );
02341 }
02342 
02343 int config_generic_wrapper( Backend *be, const char *fname, int lineno,
02344        int argc, char **argv )
02345 {
02346        ConfigArgs c = { 0 };
02347        ConfigTable *ct;
02348        int rc;
02349 
02350        c.be = be;
02351        c.fname = fname;
02352        c.lineno = lineno;
02353        c.argc = argc;
02354        c.argv = argv;
02355        c.valx = -1;
02356        c.line = line;
02357        c.op = SLAP_CONFIG_ADD;
02358        snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
02359 
02360        rc = SLAP_CONF_UNKNOWN;
02361        ct = config_find_keyword( be->be_cf_ocs->co_table, &c );
02362        if ( ct ) {
02363               c.table = be->be_cf_ocs->co_type;
02364               rc = config_add_vals( ct, &c );
02365        }
02366        return rc;
02367 }
02368 
02369 /* See if the given URL (in plain and parsed form) matches
02370  * any of the server's listener addresses. Return matching
02371  * Listener or NULL for no match.
02372  */
02373 Listener *config_check_my_url( const char *url, LDAPURLDesc *lud )
02374 {
02375        Listener **l = slapd_get_listeners();
02376        int i, isMe;
02377 
02378        /* Try a straight compare with Listener strings */
02379        for ( i=0; l && l[i]; i++ ) {
02380               if ( !strcasecmp( url, l[i]->sl_url.bv_val )) {
02381                      return l[i];
02382               }
02383        }
02384 
02385        isMe = 0;
02386        /* If hostname is empty, or is localhost, or matches
02387         * our hostname, this url refers to this host.
02388         * Compare it against listeners and ports.
02389         */
02390        if ( !lud->lud_host || !lud->lud_host[0] ||
02391               !strncasecmp("localhost", lud->lud_host,
02392                      STRLENOF("localhost")) ||
02393               !strcasecmp( global_host, lud->lud_host )) {
02394 
02395               for ( i=0; l && l[i]; i++ ) {
02396                      LDAPURLDesc *lu2;
02397                      ldap_url_parse( l[i]->sl_url.bv_val, &lu2 );
02398                      do {
02399                             if ( strcasecmp( lud->lud_scheme,
02400                                    lu2->lud_scheme ))
02401                                    break;
02402                             if ( lud->lud_port != lu2->lud_port )
02403                                    break;
02404                             /* Listener on ANY address */
02405                             if ( !lu2->lud_host || !lu2->lud_host[0] ) {
02406                                    isMe = 1;
02407                                    break;
02408                             }
02409                             /* URL on ANY address */
02410                             if ( !lud->lud_host || !lud->lud_host[0] ) {
02411                                    isMe = 1;
02412                                    break;
02413                             }
02414                             /* Listener has specific host, must
02415                              * match it
02416                              */
02417                             if ( !strcasecmp( lud->lud_host,
02418                                    lu2->lud_host )) {
02419                                    isMe = 1;
02420                                    break;
02421                             }
02422                      } while(0);
02423                      ldap_free_urldesc( lu2 );
02424                      if ( isMe ) {
02425                             return l[i];
02426                      }
02427               }
02428        }
02429        return NULL;
02430 }