1 /*        $NetBSD: config.c,v 1.3 2021/08/14 16:14:58 christos Exp $  */
2 
3 /* config.c - configuration file handling routines */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms are permitted
22  * provided that this notice is preserved and that due credit is given
23  * to the University of Michigan at Ann Arbor. The name of the University
24  * may not be used to endorse or promote products derived from this
25  * software without specific prior written permission. This software
26  * is provided ``as is'' without express or implied warranty.
27  */
28 
29 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: config.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
31 
32 #include "portable.h"
33 
34 #include <stdio.h>
35 
36 #include <ac/string.h>
37 #include <ac/ctype.h>
38 #include <ac/signal.h>
39 #include <ac/socket.h>
40 #include <ac/errno.h>
41 #include <ac/unistd.h>
42 
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 
46 #ifndef S_ISREG
47 #define   S_ISREG(m)          (((m) & _S_IFMT) == _S_IFREG)
48 #endif
49 
50 #include "slap.h"
51 #ifdef LDAP_SLAPI
52 #include "slapi/slapi.h"
53 #endif
54 #include "lutil.h"
55 #include "lutil_ldap.h"
56 #include "ldif.h"
57 #include "slap-config.h"
58 
59 #ifdef _WIN32
60 #define   LUTIL_ATOULX        lutil_atoullx
61 #define   Z         "I"
62 #else
63 #define   LUTIL_ATOULX        lutil_atoulx
64 #define   Z         "z"
65 #endif
66 
67 #define ARGS_STEP   512
68 
69 /*
70  * defaults for various global variables
71  */
72 slap_mask_t                   global_allows = 0;
73 slap_mask_t                   global_disallows = 0;
74 int                 global_gentlehup = 0;
75 int                 global_idletimeout = 0;
76 int                 global_writetimeout = 0;
77 char      *global_host = NULL;
78 struct berval global_host_bv = BER_BVNULL;
79 char      *global_realm = NULL;
80 char      *sasl_host = NULL;
81 char      *sasl_cbinding = NULL;
82 char                **default_passwd_hash = NULL;
83 struct berval default_search_base = BER_BVNULL;
84 struct berval default_search_nbase = BER_BVNULL;
85 
86 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
87 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
88 
89 int       slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
90 int       slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
91 
92 int       slap_max_filter_depth = SLAP_MAX_FILTER_DEPTH_DEFAULT;
93 
94 char   *slapd_pid_file  = NULL;
95 char   *slapd_args_file = NULL;
96 
97 int use_reverse_lookup = 0;
98 
99 #ifdef LDAP_SLAPI
100 int slapi_plugins_used = 0;
101 #endif
102 
103 static int fp_getline(FILE *fp, ConfigArgs *c);
104 static void fp_getline_init(ConfigArgs *c);
105 
106 static char         *strtok_quote(char *line, char *sep, char **quote_ptr, int *inquote);
107 static char *strtok_quote_ldif(char **line);
108 
109 ConfigArgs *
new_config_args(BackendDB * be,const char * fname,int lineno,int argc,char ** argv)110 new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **argv )
111 {
112           ConfigArgs *c;
113           c = ch_calloc( 1, sizeof( ConfigArgs ) );
114           if ( c == NULL ) return(NULL);
115           c->be     = be;
116           c->fname  = fname;
117           c->argc   = argc;
118           c->argv   = argv;
119           c->lineno = lineno;
120           snprintf( c->log, sizeof( c->log ), "%s: line %d", fname, lineno );
121           return(c);
122 }
123 
124 void
init_config_argv(ConfigArgs * c)125 init_config_argv( ConfigArgs *c )
126 {
127           c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
128           c->argv_size = ARGS_STEP + 1;
129 }
130 
config_find_keyword(ConfigTable * Conf,ConfigArgs * c)131 ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
132           int i;
133 
134           for(i = 0; Conf[i].name; i++)
135                     if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
136                               (!strcasecmp(c->argv[0], Conf[i].name)) ) break;
137           if ( !Conf[i].name ) return NULL;
138           if (( Conf[i].arg_type & ARGS_TYPES ) == ARG_BINARY ) {
139                     size_t decode_len = LUTIL_BASE64_DECODE_LEN(c->linelen);
140                     ch_free( c->tline );
141                     c->tline = ch_malloc( decode_len+1 );
142                     c->linelen = lutil_b64_pton( c->line, c->tline, decode_len );
143                     if ( c->linelen < 0 )
144                     {
145                               ch_free( c->tline );
146                               c->tline = NULL;
147                               return NULL;
148                     }
149                     c->line = c->tline;
150           }
151           return Conf+i;
152 }
153 
config_check_vals(ConfigTable * Conf,ConfigArgs * c,int check_only)154 int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
155           int rc, arg_user, arg_type, arg_syn, iarg;
156           unsigned uiarg;
157           long larg;
158           size_t ularg;
159           ber_len_t barg;
160 
161           if(Conf->arg_type == ARG_IGNORED) {
162                     Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
163                               c->log, Conf->name );
164                     return(0);
165           }
166           arg_type = Conf->arg_type & ARGS_TYPES;
167           arg_user = Conf->arg_type & ARGS_USERLAND;
168           arg_syn = Conf->arg_type & ARGS_SYNTAX;
169 
170           if((arg_type == ARG_DN) && c->argc == 1) {
171                     c->argc = 2;
172                     c->argv[1] = "";
173           }
174           if(Conf->min_args && (c->argc < Conf->min_args)) {
175                     snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> missing <%s> argument",
176                               c->argv[0], Conf->what ? Conf->what : "" );
177                     Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", c->log, c->cr_msg );
178                     return(ARG_BAD_CONF);
179           }
180           if(Conf->max_args && (c->argc > Conf->max_args)) {
181                     char      *ignored = " ignored";
182 
183                     snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> extra cruft after <%s>",
184                               c->argv[0], Conf->what );
185 
186                     ignored = "";
187                     Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s%s.\n",
188                                         c->log, c->cr_msg, ignored );
189                     return(ARG_BAD_CONF);
190           }
191           if((arg_syn & ARG_DB) && !c->be) {
192                     snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> only allowed within database declaration",
193                               c->argv[0] );
194                     Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
195                               c->log, c->cr_msg );
196                     return(ARG_BAD_CONF);
197           }
198           if((arg_syn & ARG_PRE_BI) && c->bi) {
199                     snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any backend %sdeclaration",
200                               c->argv[0], (arg_syn & ARG_PRE_DB) ? "or database " : "" );
201                     Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
202                               c->log, c->cr_msg );
203                     return(ARG_BAD_CONF);
204           }
205           if((arg_syn & ARG_PRE_DB) && c->be && c->be != frontendDB) {
206                     snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any database declaration",
207                               c->argv[0] );
208                     Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
209                               c->log, c->cr_msg );
210                     return(ARG_BAD_CONF);
211           }
212           if((arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
213                     snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> old format not supported", c->argv[0] );
214                     Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
215                               c->log, c->cr_msg );
216                     return(ARG_BAD_CONF);
217           }
218           if(arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET)) {
219                     snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid config_table, arg_item is NULL",
220                               c->argv[0] );
221                     Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
222                               c->log, c->cr_msg );
223                     return(ARG_BAD_CONF);
224           }
225           c->type = arg_user;
226           memset(&c->values, 0, sizeof(c->values));
227           if(arg_type == ARG_STRING) {
228                     assert( c->argc == 2 );
229                     if ( !check_only )
230                               c->value_string = ch_strdup(c->argv[1]);
231           } else if(arg_type == ARG_BERVAL) {
232                     assert( c->argc == 2 );
233                     if ( !check_only )
234                               ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
235           } else if(arg_type == ARG_BINARY) {
236                     assert( c->argc == 2 );
237                     if ( !check_only ) {
238                               c->value_bv.bv_len = c->linelen;
239                               c->value_bv.bv_val = ch_malloc( c->linelen );
240                               AC_MEMCPY( c->value_bv.bv_val, c->line, c->linelen );
241                     }
242           } else if(arg_type == ARG_DN) {
243                     struct berval bv;
244                     assert( c->argc == 2 );
245                     ber_str2bv( c->argv[1], 0, 0, &bv );
246                     rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
247                     if ( rc != LDAP_SUCCESS ) {
248                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid DN %d (%s)",
249                                         c->argv[0], rc, ldap_err2string( rc ));
250                               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg );
251                               return(ARG_BAD_CONF);
252                     }
253                     if ( check_only ) {
254                               ch_free( c->value_ndn.bv_val );
255                               ch_free( c->value_dn.bv_val );
256                     }
257           } else if(arg_type == ARG_ATDESC) {
258                     const char *text = NULL;
259                     assert( c->argc == 2 );
260                     c->value_ad = NULL;
261                     rc = slap_str2ad( c->argv[1], &c->value_ad, &text );
262                     if ( rc != LDAP_SUCCESS ) {
263                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid AttributeDescription %d (%s)",
264                                         c->argv[0], rc, text );
265                               Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg );
266                               return(ARG_BAD_CONF);
267                     }
268           } else {  /* all numeric */
269                     int j;
270                     iarg = 0; larg = 0; barg = 0;
271                     switch(arg_type) {
272                               case ARG_INT:
273                                         assert( c->argc == 2 );
274                                         if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
275                                                   snprintf( c->cr_msg, sizeof( c->cr_msg ),
276                                                             "<%s> unable to parse \"%s\" as int",
277                                                             c->argv[0], c->argv[1] );
278                                                   Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
279                                                             c->log, c->cr_msg );
280                                                   return(ARG_BAD_CONF);
281                                         }
282                                         break;
283                               case ARG_UINT:
284                                         assert( c->argc == 2 );
285                                         if ( lutil_atoux( &uiarg, c->argv[1], 0 ) != 0 ) {
286                                                   snprintf( c->cr_msg, sizeof( c->cr_msg ),
287                                                             "<%s> unable to parse \"%s\" as unsigned int",
288                                                             c->argv[0], c->argv[1] );
289                                                   Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
290                                                             c->log, c->cr_msg );
291                                                   return(ARG_BAD_CONF);
292                                         }
293                                         break;
294                               case ARG_LONG:
295                                         assert( c->argc == 2 );
296                                         if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
297                                                   snprintf( c->cr_msg, sizeof( c->cr_msg ),
298                                                             "<%s> unable to parse \"%s\" as long",
299                                                             c->argv[0], c->argv[1] );
300                                                   Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
301                                                             c->log, c->cr_msg );
302                                                   return(ARG_BAD_CONF);
303                                         }
304                                         break;
305                               case ARG_ULONG:
306                                         assert( c->argc == 2 );
307                                         if ( LUTIL_ATOULX( &ularg, c->argv[1], 0 ) != 0 ) {
308                                                   snprintf( c->cr_msg, sizeof( c->cr_msg ),
309                                                             "<%s> unable to parse \"%s\" as unsigned long",
310                                                             c->argv[0], c->argv[1] );
311                                                   Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
312                                                             c->log, c->cr_msg );
313                                                   return(ARG_BAD_CONF);
314                                         }
315                                         break;
316                               case ARG_BER_LEN_T: {
317                                         unsigned long       l;
318                                         assert( c->argc == 2 );
319                                         if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
320                                                   snprintf( c->cr_msg, sizeof( c->cr_msg ),
321                                                             "<%s> unable to parse \"%s\" as ber_len_t",
322                                                             c->argv[0], c->argv[1] );
323                                                   Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
324                                                             c->log, c->cr_msg );
325                                                   return(ARG_BAD_CONF);
326                                         }
327                                         barg = (ber_len_t)l;
328                                         } break;
329                               case ARG_ON_OFF:
330                                         /* note: this is an explicit exception
331                                          * to the "need exactly 2 args" rule */
332                                         if (c->argc == 1) {
333                                                   iarg = 1;
334                                         } else if ( !strcasecmp(c->argv[1], "on") ||
335                                                   !strcasecmp(c->argv[1], "true") ||
336                                                   !strcasecmp(c->argv[1], "yes") )
337                                         {
338                                                   iarg = 1;
339                                         } else if ( !strcasecmp(c->argv[1], "off") ||
340                                                   !strcasecmp(c->argv[1], "false") ||
341                                                   !strcasecmp(c->argv[1], "no") )
342                                         {
343                                                   iarg = 0;
344                                         } else {
345                                                   snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
346                                                             c->argv[0] );
347                                                   Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
348                                                             c->log, c->cr_msg );
349                                                   return(ARG_BAD_CONF);
350                                         }
351                                         break;
352                     }
353                     j = (arg_type & ARG_NONZERO) ? 1 : 0;
354                     if(iarg < j && larg < j && barg < (unsigned)j ) {
355                               larg = larg ? larg : (barg ? (long)barg : iarg);
356                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
357                                         c->argv[0] );
358                               Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
359                                         c->log, c->cr_msg );
360                               return(ARG_BAD_CONF);
361                     }
362                     switch(arg_type) {
363                               case ARG_ON_OFF:
364                               case ARG_INT:                 c->value_int = iarg;                    break;
365                               case ARG_UINT:                c->value_uint = uiarg;                  break;
366                               case ARG_LONG:                c->value_long = larg;                   break;
367                               case ARG_ULONG:               c->value_ulong = ularg;                 break;
368                               case ARG_BER_LEN_T: c->value_ber_t = barg;                  break;
369                     }
370           }
371           return 0;
372 }
373 
config_set_vals(ConfigTable * Conf,ConfigArgs * c)374 int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
375           int rc, arg_type;
376           void *ptr = NULL;
377 
378           arg_type = Conf->arg_type;
379           if(arg_type & ARG_MAGIC) {
380                     if(!c->be) c->be = frontendDB;
381                     c->cr_msg[0] = '\0';
382                     rc = (*((ConfigDriver*)Conf->arg_item))(c);
383 #if 0
384                     if(c->be == frontendDB) c->be = NULL;
385 #endif
386                     if(rc) {
387                               if ( !c->cr_msg[0] ) {
388                                         snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> handler exited with %d",
389                                                   c->argv[0], rc );
390                                         Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
391                                                   c->log, c->cr_msg );
392                               }
393                               return(ARG_BAD_CONF);
394                     }
395                     return(0);
396           }
397           if(arg_type & ARG_OFFSET) {
398                     if (c->be && c->table == Cft_Database)
399                               ptr = c->be->be_private;
400                     else if (c->bi)
401                               ptr = c->bi->bi_private;
402                     else {
403                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> offset is missing base pointer",
404                                         c->argv[0] );
405                               Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
406                                         c->log, c->cr_msg );
407                               return(ARG_BAD_CONF);
408                     }
409                     ptr = (void *)((char *)ptr + (long)Conf->arg_item);
410           } else if (arg_type & ARGS_TYPES) {
411                     ptr = Conf->arg_item;
412           }
413           if(arg_type & ARGS_TYPES)
414                     switch(arg_type & ARGS_TYPES) {
415                               case ARG_ON_OFF:
416                               case ARG_INT:                 *(int*)ptr = c->value_int;                        break;
417                               case ARG_UINT:                *(unsigned*)ptr = c->value_uint;                            break;
418                               case ARG_LONG:      *(long*)ptr = c->value_long;                      break;
419                               case ARG_ULONG:     *(size_t*)ptr = c->value_ulong;                             break;
420                               case ARG_BER_LEN_T:           *(ber_len_t*)ptr = c->value_ber_t;                          break;
421                               case ARG_STRING: {
422                                         char *cc = *(char**)ptr;
423                                         if(cc) {
424                                                   if ((arg_type & ARG_UNIQUE) && c->op == SLAP_CONFIG_ADD ) {
425                                                             Debug(LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
426                                                                       c->log, Conf->name );
427                                                             return(ARG_BAD_CONF);
428                                                   }
429                                                   ch_free(cc);
430                                         }
431                                         *(char **)ptr = c->value_string;
432                                         break;
433                                         }
434                               case ARG_BERVAL:
435                               case ARG_BINARY:
436                                         *(struct berval *)ptr = c->value_bv;
437                                         break;
438                               case ARG_ATDESC:
439                                         *(AttributeDescription **)ptr = c->value_ad;
440                                         break;
441                     }
442           return(0);
443 }
444 
config_add_vals(ConfigTable * Conf,ConfigArgs * c)445 int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
446           int rc, arg_type;
447 
448           arg_type = Conf->arg_type;
449           if(arg_type == ARG_IGNORED) {
450                     Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
451                               c->log, Conf->name );
452                     return(0);
453           }
454           rc = config_check_vals( Conf, c, 0 );
455           if ( rc ) return rc;
456           return config_set_vals( Conf, c );
457 }
458 
459 int
config_del_vals(ConfigTable * cf,ConfigArgs * c)460 config_del_vals(ConfigTable *cf, ConfigArgs *c)
461 {
462           int rc = 0;
463           void *ptr;
464 
465           if ( cf->arg_type & ARG_MAGIC ) {
466                     c->argv[0] = cf->ad->ad_cname.bv_val;
467                     c->op = LDAP_MOD_DELETE;
468                     c->type = cf->arg_type & ARGS_USERLAND;
469                     rc = (*((ConfigDriver*)cf->arg_item))(c);
470                     return rc;
471           }
472           /* If there is no handler, just zero it */
473           if ( cf->arg_type & ARG_OFFSET ) {
474                     if ( c->be && c->table == Cft_Database )
475                               ptr = c->be->be_private;
476                     else if ( c->bi )
477                               ptr = c->bi->bi_private;
478                     else {
479                               snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> offset is missing base pointer",
480                                         c->argv[0] );
481                               Debug( LDAP_DEBUG_CONFIG, "%s: %s!\n",
482                                         c->log, c->cr_msg );
483                               return ARG_BAD_CONF;
484                     }
485                     ptr = (void *)((char *)ptr + (long)cf->arg_item);
486           } else if ( cf->arg_type & ARGS_TYPES ) {
487                     ptr = cf->arg_item;
488           }
489           if ( cf->arg_type & ARGS_TYPES )
490                     switch ( cf->arg_type & ARGS_TYPES ) {
491                               case ARG_ON_OFF:
492                               case ARG_INT:                 *(int *)ptr = cf->arg_default.v_int;              break;
493                               case ARG_UINT:                *(unsigned *)ptr = cf->arg_default.v_uint;        break;
494                               case ARG_LONG:                *(long *)ptr = cf->arg_default.v_long;            break;
495                               case ARG_ULONG:               *(size_t *)ptr = cf->arg_default.v_ulong;         break;
496                               case ARG_BER_LEN_T: *(ber_len_t *)ptr = cf->arg_default.v_ber_t;      break;
497                               case ARG_STRING:
498                                         ch_free( *(char**)ptr );
499                                         if ( cf->arg_default.v_string ) {
500                                                   *(char **)ptr = ch_strdup( cf->arg_default.v_string );
501                                         } else {
502                                                   *(char **)ptr = NULL;
503                                         }
504                                         break;
505                               case ARG_BERVAL:
506                               case ARG_BINARY:
507                                         ch_free( ((struct berval *)ptr)->bv_val );
508                                         if ( !BER_BVISNULL( &cf->arg_default.v_bv ) ) {
509                                                   ber_dupbv( (struct berval *)ptr, &cf->arg_default.v_bv );
510                                         } else {
511                                                   BER_BVZERO( (struct berval *)ptr );
512                                         }
513                                         break;
514                               case ARG_ATDESC:
515                                         *(AttributeDescription **)ptr = cf->arg_default.v_ad;
516                                         break;
517                     }
518           return rc;
519 }
520 
521 int
config_get_vals(ConfigTable * cf,ConfigArgs * c)522 config_get_vals(ConfigTable *cf, ConfigArgs *c)
523 {
524           int rc = 0;
525           struct berval bv;
526           void *ptr;
527 
528           if ( cf->arg_type & ARG_IGNORED ) {
529                     return 1;
530           }
531 
532           memset(&c->values, 0, sizeof(c->values));
533           c->rvalue_vals = NULL;
534           c->rvalue_nvals = NULL;
535           c->op = SLAP_CONFIG_EMIT;
536           c->type = cf->arg_type & ARGS_USERLAND;
537 
538           if ( cf->arg_type & ARG_MAGIC ) {
539                     rc = (*((ConfigDriver*)cf->arg_item))(c);
540                     if ( rc ) return rc;
541           } else {
542                     if ( cf->arg_type & ARG_OFFSET ) {
543                               if (c->be && c->table == Cft_Database)
544                                         ptr = c->be->be_private;
545                               else if ( c->bi )
546                                         ptr = c->bi->bi_private;
547                               else
548                                         return 1;
549                               ptr = (void *)((char *)ptr + (long)cf->arg_item);
550                     } else {
551                               ptr = cf->arg_item;
552                     }
553 
554                     switch(cf->arg_type & ARGS_TYPES) {
555                     case ARG_ON_OFF:
556                     case ARG_INT:       c->value_int = *(int *)ptr; break;
557                     case ARG_UINT:      c->value_uint = *(unsigned *)ptr; break;
558                     case ARG_LONG:      c->value_long = *(long *)ptr; break;
559                     case ARG_ULONG:     c->value_ulong = *(size_t *)ptr; break;
560                     case ARG_BER_LEN_T: c->value_ber_t = *(ber_len_t *)ptr; break;
561                     case ARG_STRING:
562                               if ( *(char **)ptr )
563                                         c->value_string = ch_strdup(*(char **)ptr);
564                               break;
565                     case ARG_BERVAL:
566                               c->value_bv = *((struct berval *)ptr); break;
567                     case ARG_ATDESC:
568                               c->value_ad = *(AttributeDescription **)ptr; break;
569                     }
570           }
571           if ( cf->arg_type & ARGS_TYPES) {
572                     bv.bv_len = 0;
573                     bv.bv_val = c->log;
574                     switch(cf->arg_type & ARGS_TYPES) {
575                     case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
576                     case ARG_UINT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%u", c->value_uint); break;
577                     case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
578                     case ARG_ULONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%" Z "u", c->value_ulong); break;
579                     case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
580                     case ARG_ON_OFF: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%s",
581                               c->value_int ? "TRUE" : "FALSE"); break;
582                     case ARG_STRING:
583                               if ( c->value_string && c->value_string[0]) {
584                                         ber_str2bv( c->value_string, 0, 0, &bv);
585                               } else {
586                                         return 1;
587                               }
588                               break;
589                     case ARG_BERVAL:
590                               if ( !BER_BVISEMPTY( &c->value_bv )) {
591                                         bv = c->value_bv;
592                               } else {
593                                         return 1;
594                               }
595                               break;
596                     case ARG_ATDESC:
597                               if ( c->value_ad ) {
598                                         bv = c->value_ad->ad_cname;
599                               } else {
600                                         return 1;
601                               }
602                               break;
603                     default:
604                               bv.bv_val = NULL;
605                               break;
606                     }
607                     if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) {
608                               return 1;
609                     }
610                     if (( cf->arg_type & ARGS_TYPES ) == ARG_STRING ) {
611                               ber_bvarray_add(&c->rvalue_vals, &bv);
612                     } else if ( !BER_BVISNULL( &bv ) ) {
613                               value_add_one(&c->rvalue_vals, &bv);
614                     }
615                     /* else: maybe c->rvalue_vals already set? */
616           }
617           return rc;
618 }
619 
620 int
config_push_cleanup(ConfigArgs * ca,ConfigDriver * cleanup)621 config_push_cleanup(ConfigArgs *ca, ConfigDriver *cleanup)
622 {
623           int i;
624           /* silently ignore redundant push */
625           for (i=0; i < ca->num_cleanups; i++) {
626                     if ( ca->cleanups[i] == cleanup )
627                               return 0;
628           }
629 
630           if (ca->num_cleanups >= SLAP_CONFIG_CLEANUP_MAX)
631                     return -1;
632           ca->cleanups[ca->num_cleanups++] = cleanup;
633           return 0;
634 }
635 
636 int
config_run_cleanup(ConfigArgs * ca)637 config_run_cleanup(ConfigArgs *ca)
638 {
639           int i, rc = 0;
640 
641           for (i=0; i < ca->num_cleanups; i++) {
642                     rc = ca->cleanups[i](ca);
643                     if (rc)
644                               break;
645           }
646           return rc;
647 }
648 
649 int
init_config_attrs(ConfigTable * ct)650 init_config_attrs(ConfigTable *ct) {
651           int i, code;
652 
653           for (i=0; ct[i].name; i++ ) {
654                     if ( !ct[i].attribute ) continue;
655                     code = register_at( ct[i].attribute, &ct[i].ad, 1 );
656                     if ( code ) {
657                               fprintf( stderr, "init_config_attrs: register_at failed\n" );
658                               return code;
659                     }
660                     if (( ct[i].arg_type & ARGS_TYPES ) == ARG_BINARY ) {
661                               ldif_must_b64_encode_register( ct[i].ad->ad_cname.bv_val,
662                                         ct[i].ad->ad_type->sat_oid );
663                     }
664           }
665 
666           return 0;
667 }
668 
669 int
init_config_ocs(ConfigOCs * ocs)670 init_config_ocs( ConfigOCs *ocs ) {
671           int i, code;
672 
673           for (i=0;ocs[i].co_def;i++) {
674                     code = register_oc( ocs[i].co_def, &ocs[i].co_oc, 1 );
675                     if ( code ) {
676                               fprintf( stderr, "init_config_ocs: register_oc failed\n" );
677                               return code;
678                     }
679           }
680           return 0;
681 }
682 
683 /* Split an LDIF line into space-separated tokens. Words may be grouped
684  * by quotes. A quoted string may begin in the middle of a word, but must
685  * end at the end of the word (be followed by whitespace or EOS). Any other
686  * quotes are passed through unchanged. All other characters are passed
687  * through unchanged.
688  */
689 static char *
strtok_quote_ldif(char ** line)690 strtok_quote_ldif( char **line )
691 {
692           char *beg, *ptr, *quote=NULL;
693           int inquote=0;
694 
695           ptr = *line;
696 
697           if ( !ptr || !*ptr )
698                     return NULL;
699 
700           while( isspace( (unsigned char) *ptr )) ptr++;
701 
702           if ( *ptr == '"' ) {
703                     inquote = 1;
704                     ptr++;
705           }
706 
707           beg = ptr;
708 
709           for (;*ptr;ptr++) {
710                     if ( *ptr == '"' ) {
711                               if ( inquote && ( !ptr[1] || isspace((unsigned char) ptr[1]))) {
712                                         *ptr++ = '\0';
713                                         break;
714                               }
715                               inquote = 1;
716                               quote = ptr;
717                               continue;
718                     }
719                     if ( inquote )
720                               continue;
721                     if ( isspace( (unsigned char) *ptr )) {
722                               *ptr++ = '\0';
723                               break;
724                     }
725           }
726           if ( quote ) {
727                     while ( quote < ptr ) {
728                               *quote = quote[1];
729                               quote++;
730                     }
731           }
732           if ( !*ptr ) {
733                     *line = NULL;
734           } else {
735                     while ( isspace( (unsigned char) *ptr )) ptr++;
736                     *line = ptr;
737           }
738           return beg;
739 }
740 
741 void
config_parse_ldif(ConfigArgs * c)742 config_parse_ldif( ConfigArgs *c )
743 {
744           char *next;
745           c->tline = ch_strdup(c->line);
746           next = c->tline;
747 
748           while ((c->argv[c->argc] = strtok_quote_ldif( &next )) != NULL) {
749                     c->argc++;
750                     if ( c->argc >= c->argv_size ) {
751                               char **tmp = ch_realloc( c->argv, (c->argv_size + ARGS_STEP) *
752                                         sizeof( *c->argv ));
753                               c->argv = tmp;
754                               c->argv_size += ARGS_STEP;
755                     }
756           }
757           c->argv[c->argc] = NULL;
758 }
759 
760 int
config_parse_vals(ConfigTable * ct,ConfigArgs * c,int valx)761 config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
762 {
763           int       rc = 0;
764           int arg_type = ct->arg_type & ARGS_TYPES;
765 
766           snprintf( c->log, sizeof( c->log ), "%s: value #%d",
767                     ct->ad->ad_cname.bv_val, valx );
768           c->argc = 1;
769           c->argv[0] = ct->ad->ad_cname.bv_val;
770 
771           if ( (( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) ||
772                     (arg_type == ARG_BERVAL || arg_type == ARG_BINARY)) {
773                     c->argv[c->argc] = c->line;
774                     c->argc++;
775                     c->argv[c->argc] = NULL;
776                     c->tline = NULL;
777           } else {
778                     config_parse_ldif( c );
779           }
780           rc = config_check_vals( ct, c, 1 );
781           ch_free( c->tline );
782           c->tline = NULL;
783 
784           if ( rc )
785                     rc = LDAP_CONSTRAINT_VIOLATION;
786 
787           return rc;
788 }
789 
790 int
config_parse_add(ConfigTable * ct,ConfigArgs * c,int valx)791 config_parse_add(ConfigTable *ct, ConfigArgs *c, int valx)
792 {
793           int       rc = 0;
794           int arg_type = ct->arg_type & ARGS_TYPES;
795 
796           snprintf( c->log, sizeof( c->log ), "%s: value #%d",
797                     ct->ad->ad_cname.bv_val, valx );
798           c->argc = 1;
799           c->argv[0] = ct->ad->ad_cname.bv_val;
800 
801           if ( (( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) ||
802                     (arg_type == ARG_BERVAL || arg_type == ARG_BINARY)) {
803                     c->argv[c->argc] = c->line;
804                     c->argc++;
805                     c->argv[c->argc] = NULL;
806                     c->tline = NULL;
807           } else {
808                     config_parse_ldif( c );
809           }
810           c->op = LDAP_MOD_ADD;
811           rc = config_add_vals( ct, c );
812           ch_free( c->tline );
813 
814           return rc;
815 }
816 
817 int
read_config_file(const char * fname,int depth,ConfigArgs * cf,ConfigTable * cft)818 read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
819 {
820           FILE *fp;
821           ConfigTable *ct;
822           ConfigArgs *c;
823           int rc;
824           struct stat s;
825 
826           c = ch_calloc( 1, sizeof( ConfigArgs ) );
827           if ( c == NULL ) {
828                     return 1;
829           }
830 
831           if ( depth ) {
832                     memcpy( c, cf, sizeof( ConfigArgs ) );
833           } else {
834                     c->depth = depth; /* XXX */
835                     c->bi = NULL;
836                     c->be = NULL;
837           }
838 
839           c->valx = -1;
840           c->fname = fname;
841           init_config_argv( c );
842 
843           if ( stat( fname, &s ) != 0 ) {
844                     char ebuf[128];
845                     int saved_errno = errno;
846                     ldap_syslog = 1;
847                     Debug(LDAP_DEBUG_ANY,
848                         "could not stat config file \"%s\": %s (%d)\n",
849                         fname, AC_STRERROR_R( saved_errno, ebuf, sizeof(ebuf) ), saved_errno);
850                     ch_free( c->argv );
851                     ch_free( c );
852                     return(1);
853           }
854 
855           if ( !S_ISREG( s.st_mode ) ) {
856                     ldap_syslog = 1;
857                     Debug(LDAP_DEBUG_ANY,
858                         "regular file expected, got \"%s\"\n",
859                         fname );
860                     ch_free( c->argv );
861                     ch_free( c );
862                     return(1);
863           }
864 
865           fp = fopen( fname, "r" );
866           if ( fp == NULL ) {
867                     char ebuf[128];
868                     int saved_errno = errno;
869                     ldap_syslog = 1;
870                     Debug(LDAP_DEBUG_ANY,
871                         "could not open config file \"%s\": %s (%d)\n",
872                         fname, AC_STRERROR_R( saved_errno, ebuf, sizeof(ebuf) ), saved_errno);
873                     ch_free( c->argv );
874                     ch_free( c );
875                     return(1);
876           }
877 
878           Debug(LDAP_DEBUG_CONFIG, "reading config file %s\n", fname );
879 
880           fp_getline_init(c);
881 
882           c->tline = NULL;
883 
884           while ( fp_getline( fp, c ) ) {
885                     /* skip comments and blank lines */
886                     if ( c->line[0] == '#' || c->line[0] == '\0' ) {
887                               continue;
888                     }
889 
890                     snprintf( c->log, sizeof( c->log ), "%s: line %d",
891                                         c->fname, c->lineno );
892 
893                     c->argc = 0;
894                     ch_free( c->tline );
895                     if ( config_fp_parse_line( c ) ) {
896                               rc = 1;
897                               goto done;
898                     }
899 
900                     if ( c->argc < 1 ) {
901                               Debug( LDAP_DEBUG_ANY, "%s: bad config line.\n",
902                                         c->log );
903                               rc = 1;
904                               goto done;
905                     }
906 
907                     c->op = SLAP_CONFIG_ADD;
908 
909                     ct = config_find_keyword( cft, c );
910                     if ( ct ) {
911                               c->table = Cft_Global;
912                               rc = config_add_vals( ct, c );
913                               if ( !rc ) continue;
914 
915                               if ( rc & ARGS_USERLAND ) {
916                                         /* XXX a usertype would be opaque here */
917                                         Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
918                                                   c->log, c->argv[0] );
919                                         rc = 1;
920                                         goto done;
921 
922                               } else if ( rc == ARG_BAD_CONF ) {
923                                         rc = 1;
924                                         goto done;
925                               }
926 
927                     } else if ( ( c->bi && !c->be ) || ( c->bi && c->bi->bi_flags & SLAP_BFLAG_STANDALONE ) ) {
928                               rc = SLAP_CONF_UNKNOWN;
929                               if ( c->bi->bi_cf_ocs ) {
930                                         ct = config_find_keyword( c->bi->bi_cf_ocs->co_table, c );
931                                         if ( ct ) {
932                                                   c->table = c->bi->bi_cf_ocs->co_type;
933                                                   rc = config_add_vals( ct, c );
934                                         }
935                               }
936                               if ( c->bi->bi_config && rc == SLAP_CONF_UNKNOWN ) {
937                                         rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno,
938                                                   c->argc, c->argv);
939                               }
940                               if ( rc ) {
941                                         switch(rc) {
942                                         case SLAP_CONF_UNKNOWN:
943                                                   Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
944                                                             "<%s> inside backend info definition.\n",
945                                                             c->log, *c->argv );
946                                         default:
947                                                   rc = 1;
948                                                   goto done;
949                                         }
950                               }
951 
952                     } else if ( c->be && c->be != frontendDB ) {
953                               rc = SLAP_CONF_UNKNOWN;
954                               if ( c->be->be_cf_ocs ) {
955                                         ct = config_find_keyword( c->be->be_cf_ocs->co_table, c );
956                                         if ( ct ) {
957                                                   c->table = c->be->be_cf_ocs->co_type;
958                                                   rc = config_add_vals( ct, c );
959                                         }
960                               }
961                               if ( c->be->be_config && rc == SLAP_CONF_UNKNOWN ) {
962                                         rc = (*c->be->be_config)(c->be, c->fname, c->lineno,
963                                                   c->argc, c->argv);
964                               }
965                               if ( rc == SLAP_CONF_UNKNOWN && SLAP_ISGLOBALOVERLAY( frontendDB ) )
966                               {
967                                         /* global overlays may need
968                                          * definitions inside other databases...
969                                          */
970                                         rc = (*frontendDB->be_config)( frontendDB,
971                                                   c->fname, (int)c->lineno, c->argc, c->argv );
972                               }
973 
974                               switch ( rc ) {
975                               case 0:
976                                         break;
977 
978                               case SLAP_CONF_UNKNOWN:
979                                         Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
980                                                   "<%s> inside backend database definition.\n",
981                                                   c->log, *c->argv );
982 
983                               default:
984                                         rc = 1;
985                                         goto done;
986                               }
987 
988                     } else if ( frontendDB->be_config ) {
989                               rc = (*frontendDB->be_config)( frontendDB,
990                                         c->fname, (int)c->lineno, c->argc, c->argv);
991                               if ( rc ) {
992                                         switch(rc) {
993                                         case SLAP_CONF_UNKNOWN:
994                                                   Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
995                                                             "<%s> inside global database definition.\n",
996                                                             c->log, *c->argv );
997 
998                                         default:
999                                                   rc = 1;
1000                                                   goto done;
1001                                         }
1002                               }
1003 
1004                     } else {
1005                               Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
1006                                         "<%s> outside backend info and database definitions.\n",
1007                                         c->log, *c->argv );
1008                               rc = 1;
1009                               goto done;
1010                     }
1011           }
1012 
1013           rc = 0;
1014 
1015 done:
1016           if ( cf ) {
1017                     cf->be = c->be;
1018                     cf->bi = c->bi;
1019           }
1020           ch_free(c->tline);
1021           fclose(fp);
1022           ch_free(c->argv);
1023           ch_free(c);
1024           return(rc);
1025 }
1026 
1027 /* restrictops, allows, disallows, requires, loglevel */
1028 
1029 int
bverb_to_mask(struct berval * bword,slap_verbmasks * v)1030 bverb_to_mask(struct berval *bword, slap_verbmasks *v) {
1031           int i;
1032           for(i = 0; !BER_BVISNULL(&v[i].word); i++) {
1033                     if(!ber_bvstrcasecmp(bword, &v[i].word)) break;
1034           }
1035           return(i);
1036 }
1037 
1038 int
verb_to_mask(const char * word,slap_verbmasks * v)1039 verb_to_mask(const char *word, slap_verbmasks *v) {
1040           struct berval       bword;
1041           ber_str2bv( word, 0, 0, &bword );
1042           return bverb_to_mask( &bword, v );
1043 }
1044 
1045 int
verbs_to_mask(int argc,char * argv[],slap_verbmasks * v,slap_mask_t * m)1046 verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) {
1047           int i, j;
1048           for(i = 1; i < argc; i++) {
1049                     j = verb_to_mask(argv[i], v);
1050                     if(BER_BVISNULL(&v[j].word)) return i;
1051                     while (!v[j].mask) j--;
1052                     *m |= v[j].mask;
1053           }
1054           return(0);
1055 }
1056 
1057 /* Mask keywords that represent multiple bits should occur before single
1058  * bit keywords in the verbmasks array.
1059  */
1060 int
mask_to_verbs(slap_verbmasks * v,slap_mask_t m,BerVarray * bva)1061 mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) {
1062           int i, rc = 1;
1063 
1064           if (m) {
1065                     for (i=0; !BER_BVISNULL(&v[i].word); i++) {
1066                               if (!v[i].mask) continue;
1067                               if (( m & v[i].mask ) == v[i].mask ) {
1068                                         value_add_one( bva, &v[i].word );
1069                                         rc = 0;
1070                                         m ^= v[i].mask;
1071                                         if ( !m ) break;
1072                               }
1073                     }
1074           }
1075           return rc;
1076 }
1077 
1078 /* Return the verbs as a single string, separated by delim */
1079 int
mask_to_verbstring(slap_verbmasks * v,slap_mask_t m0,char delim,struct berval * bv)1080 mask_to_verbstring(slap_verbmasks *v, slap_mask_t m0, char delim, struct berval *bv)
1081 {
1082           int i, rc = 1;
1083 
1084           BER_BVZERO( bv );
1085           if (m0) {
1086                     slap_mask_t m = m0;
1087                     char *ptr;
1088                     for (i=0; !BER_BVISNULL(&v[i].word); i++) {
1089                               if (!v[i].mask) continue;
1090                               if (( m & v[i].mask ) == v[i].mask ) {
1091                                         bv->bv_len += v[i].word.bv_len + 1;
1092                                         rc = 0;
1093                                         m ^= v[i].mask;
1094                                         if ( !m ) break;
1095                               }
1096                     }
1097                     bv->bv_val = ch_malloc(bv->bv_len);
1098                     bv->bv_len--;
1099                     ptr = bv->bv_val;
1100                     m = m0;
1101                     for (i=0; !BER_BVISNULL(&v[i].word); i++) {
1102                               if (!v[i].mask) continue;
1103                               if (( m & v[i].mask ) == v[i].mask ) {
1104                                         ptr = lutil_strcopy(ptr, v[i].word.bv_val);
1105                                         *ptr++ = delim;
1106                                         m ^= v[i].mask;
1107                                         if ( !m ) break;
1108                               }
1109                     }
1110                     ptr[-1] = '\0';
1111           }
1112           return rc;
1113 }
1114 
1115 /* Parse a verbstring */
1116 int
verbstring_to_mask(slap_verbmasks * v,char * str,char delim,slap_mask_t * m)1117 verbstring_to_mask(slap_verbmasks *v, char *str, char delim, slap_mask_t *m) {
1118           int j;
1119           char *d;
1120           struct berval bv;
1121 
1122           do {
1123                     bv.bv_val = str;
1124                     d = strchr( str, delim );
1125                     if ( d )
1126                               bv.bv_len = d - str;
1127                     else
1128                               bv.bv_len = strlen( str );
1129                     j = bverb_to_mask( &bv, v );
1130                     if(BER_BVISNULL(&v[j].word)) return 1;
1131                     while (!v[j].mask) j--;
1132                     *m |= v[j].mask;
1133                     str += bv.bv_len + 1;
1134           } while ( d );
1135           return(0);
1136 }
1137 
1138 int
slap_verbmasks_init(slap_verbmasks ** vp,slap_verbmasks * v)1139 slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
1140 {
1141           int                 i;
1142 
1143           assert( *vp == NULL );
1144 
1145           for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */;
1146 
1147           *vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );
1148 
1149           for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
1150                     ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
1151                     *((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
1152           }
1153 
1154           BER_BVZERO( &(*vp)[ i ].word );
1155 
1156           return 0;
1157 }
1158 
1159 int
slap_verbmasks_destroy(slap_verbmasks * v)1160 slap_verbmasks_destroy( slap_verbmasks *v )
1161 {
1162           int                 i;
1163 
1164           assert( v != NULL );
1165 
1166           for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
1167                     ch_free( v[ i ].word.bv_val );
1168           }
1169 
1170           ch_free( v );
1171 
1172           return 0;
1173 }
1174 
1175 int
slap_verbmasks_append(slap_verbmasks ** vp,slap_mask_t m,struct berval * v,slap_mask_t * ignore)1176 slap_verbmasks_append(
1177           slap_verbmasks      **vp,
1178           slap_mask_t         m,
1179           struct berval       *v,
1180           slap_mask_t         *ignore )
1181 {
1182           int       i;
1183 
1184           if ( !m ) {
1185                     return LDAP_OPERATIONS_ERROR;
1186           }
1187 
1188           for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
1189                     if ( !(*vp)[ i ].mask ) continue;
1190 
1191                     if ( ignore != NULL ) {
1192                               int       j;
1193 
1194                               for ( j = 0; ignore[ j ] != 0; j++ ) {
1195                                         if ( (*vp)[ i ].mask == ignore[ j ] ) {
1196                                                   goto check_next;
1197                                         }
1198                               }
1199                     }
1200 
1201                     if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
1202                               if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
1203                                         /* already set; ignore */
1204                                         return LDAP_SUCCESS;
1205                               }
1206                               /* conflicts */
1207                               return LDAP_TYPE_OR_VALUE_EXISTS;
1208                     }
1209 
1210                     if ( m & (*vp)[ i ].mask ) {
1211                               /* conflicts */
1212                               return LDAP_CONSTRAINT_VIOLATION;
1213                     }
1214 check_next:;
1215           }
1216 
1217           *vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
1218           ber_dupbv( &(*vp)[ i ].word, v );
1219           *((slap_mask_t *)&(*vp)[ i ].mask) = m;
1220           BER_BVZERO( &(*vp)[ i + 1 ].word );
1221 
1222           return LDAP_SUCCESS;
1223 }
1224 
1225 int
enum_to_verb(slap_verbmasks * v,slap_mask_t m,struct berval * bv)1226 enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
1227           int i;
1228 
1229           for (i=0; !BER_BVISNULL(&v[i].word); i++) {
1230                     if ( m == v[i].mask ) {
1231                               if ( bv != NULL ) {
1232                                         *bv = v[i].word;
1233                               }
1234                               return i;
1235                     }
1236           }
1237           return -1;
1238 }
1239 
1240 /* register a new verbmask */
1241 static int
slap_verbmask_register(slap_verbmasks * vm_,slap_verbmasks ** vmp,struct berval * bv,int mask)1242 slap_verbmask_register( slap_verbmasks *vm_, slap_verbmasks **vmp, struct berval *bv, int mask )
1243 {
1244           slap_verbmasks      *vm = *vmp;
1245           int                 i;
1246 
1247           /* check for duplicate word */
1248           /* NOTE: we accept duplicate codes; the first occurrence will be used
1249            * when mapping from mask to verb */
1250           i = verb_to_mask( bv->bv_val, vm );
1251           if ( !BER_BVISNULL( &vm[ i ].word ) ) {
1252                     return -1;
1253           }
1254 
1255           for ( i = 0; !BER_BVISNULL( &vm[ i ].word ); i++ )
1256                     ;
1257 
1258           if ( vm == vm_ ) {
1259                     /* first time: duplicate array */
1260                     vm = ch_calloc( i + 2, sizeof( slap_verbmasks ) );
1261                     for ( i = 0; !BER_BVISNULL( &vm_[ i ].word ); i++ )
1262                     {
1263                               ber_dupbv( &vm[ i ].word, &vm_[ i ].word );
1264                               *((slap_mask_t*)&vm[ i ].mask) = vm_[ i ].mask;
1265                     }
1266 
1267           } else {
1268                     vm = ch_realloc( vm, (i + 2) * sizeof( slap_verbmasks ) );
1269           }
1270 
1271           ber_dupbv( &vm[ i ].word, bv );
1272           *((slap_mask_t*)&vm[ i ].mask) = mask;
1273 
1274           BER_BVZERO( &vm[ i+1 ].word );
1275 
1276           *vmp = vm;
1277 
1278           return i;
1279 }
1280 
1281 static slap_verbmasks slap_ldap_response_code_[] = {
1282           { BER_BVC("success"),                                       LDAP_SUCCESS },
1283 
1284           { BER_BVC("operationsError"),                     LDAP_OPERATIONS_ERROR },
1285           { BER_BVC("protocolError"),                       LDAP_PROTOCOL_ERROR },
1286           { BER_BVC("timelimitExceeded"),                             LDAP_TIMELIMIT_EXCEEDED },
1287           { BER_BVC("sizelimitExceeded"),                             LDAP_SIZELIMIT_EXCEEDED },
1288           { BER_BVC("compareFalse"),                        LDAP_COMPARE_FALSE },
1289           { BER_BVC("compareTrue"),                         LDAP_COMPARE_TRUE },
1290 
1291           { BER_BVC("authMethodNotSupported"),              LDAP_AUTH_METHOD_NOT_SUPPORTED },
1292           { BER_BVC("strongAuthNotSupported"),              LDAP_STRONG_AUTH_NOT_SUPPORTED },
1293           { BER_BVC("strongAuthRequired"),                  LDAP_STRONG_AUTH_REQUIRED },
1294           { BER_BVC("strongerAuthRequired"),                LDAP_STRONGER_AUTH_REQUIRED },
1295 #if 0 /* not LDAPv3 */
1296           { BER_BVC("partialResults"),                      LDAP_PARTIAL_RESULTS },
1297 #endif
1298 
1299           { BER_BVC("referral"),                                      LDAP_REFERRAL },
1300           { BER_BVC("adminlimitExceeded"),                  LDAP_ADMINLIMIT_EXCEEDED },
1301           { BER_BVC("unavailableCriticalExtension"),        LDAP_UNAVAILABLE_CRITICAL_EXTENSION },
1302           { BER_BVC("confidentialityRequired"),             LDAP_CONFIDENTIALITY_REQUIRED },
1303           { BER_BVC("saslBindInProgress"),                  LDAP_SASL_BIND_IN_PROGRESS },
1304 
1305           { BER_BVC("noSuchAttribute"),                     LDAP_NO_SUCH_ATTRIBUTE },
1306           { BER_BVC("undefinedType"),                       LDAP_UNDEFINED_TYPE },
1307           { BER_BVC("inappropriateMatching"),               LDAP_INAPPROPRIATE_MATCHING },
1308           { BER_BVC("constraintViolation"),                 LDAP_CONSTRAINT_VIOLATION },
1309           { BER_BVC("typeOrValueExists"),                             LDAP_TYPE_OR_VALUE_EXISTS },
1310           { BER_BVC("invalidSyntax"),                       LDAP_INVALID_SYNTAX },
1311 
1312           { BER_BVC("noSuchObject"),                        LDAP_NO_SUCH_OBJECT },
1313           { BER_BVC("aliasProblem"),                        LDAP_ALIAS_PROBLEM },
1314           { BER_BVC("invalidDnSyntax"),                     LDAP_INVALID_DN_SYNTAX },
1315 #if 0 /* not LDAPv3 */
1316           { BER_BVC("isLeaf"),                                        LDAP_IS_LEAF },
1317 #endif
1318           { BER_BVC("aliasDerefProblem"),                             LDAP_ALIAS_DEREF_PROBLEM },
1319 
1320           { BER_BVC("proxyAuthzFailure"),                             LDAP_X_PROXY_AUTHZ_FAILURE },
1321           { BER_BVC("inappropriateAuth"),                             LDAP_INAPPROPRIATE_AUTH },
1322           { BER_BVC("invalidCredentials"),                  LDAP_INVALID_CREDENTIALS },
1323           { BER_BVC("insufficientAccess"),                  LDAP_INSUFFICIENT_ACCESS },
1324 
1325           { BER_BVC("busy"),                                LDAP_BUSY },
1326           { BER_BVC("unavailable"),                         LDAP_UNAVAILABLE },
1327           { BER_BVC("unwillingToPerform"),                  LDAP_UNWILLING_TO_PERFORM },
1328           { BER_BVC("loopDetect"),                          LDAP_LOOP_DETECT },
1329 
1330           { BER_BVC("namingViolation"),                     LDAP_NAMING_VIOLATION },
1331           { BER_BVC("objectClassViolation"),                LDAP_OBJECT_CLASS_VIOLATION },
1332           { BER_BVC("notAllowedOnNonleaf"),                 LDAP_NOT_ALLOWED_ON_NONLEAF },
1333           { BER_BVC("notAllowedOnRdn"),                     LDAP_NOT_ALLOWED_ON_RDN },
1334           { BER_BVC("alreadyExists"),                       LDAP_ALREADY_EXISTS },
1335           { BER_BVC("noObjectClassMods"),                             LDAP_NO_OBJECT_CLASS_MODS },
1336           { BER_BVC("resultsTooLarge"),                     LDAP_RESULTS_TOO_LARGE },
1337           { BER_BVC("affectsMultipleDsas"),                 LDAP_AFFECTS_MULTIPLE_DSAS },
1338 
1339           { BER_BVC("other"),                               LDAP_OTHER },
1340 
1341           /* extension-specific */
1342 
1343           { BER_BVC("cupResourcesExhausted"),               LDAP_CUP_RESOURCES_EXHAUSTED },
1344           { BER_BVC("cupSecurityViolation"),                LDAP_CUP_SECURITY_VIOLATION },
1345           { BER_BVC("cupInvalidData"),                      LDAP_CUP_INVALID_DATA },
1346           { BER_BVC("cupUnsupportedScheme"),                LDAP_CUP_UNSUPPORTED_SCHEME },
1347           { BER_BVC("cupReloadRequired"),                             LDAP_CUP_RELOAD_REQUIRED },
1348 
1349           { BER_BVC("cancelled"),                                     LDAP_CANCELLED },
1350           { BER_BVC("noSuchOperation"),                     LDAP_NO_SUCH_OPERATION },
1351           { BER_BVC("tooLate"),                                       LDAP_TOO_LATE },
1352           { BER_BVC("cannotCancel"),                        LDAP_CANNOT_CANCEL },
1353 
1354           { BER_BVC("assertionFailed"),                     LDAP_ASSERTION_FAILED },
1355 
1356           { BER_BVC("proxiedAuthorizationDenied"),          LDAP_PROXIED_AUTHORIZATION_DENIED },
1357 
1358           { BER_BVC("syncRefreshRequired"),                 LDAP_SYNC_REFRESH_REQUIRED },
1359 
1360           { BER_BVC("noOperation"),                         LDAP_X_NO_OPERATION },
1361 
1362           { BER_BVNULL,                                     0 }
1363 };
1364 
1365 slap_verbmasks *slap_ldap_response_code = slap_ldap_response_code_;
1366 
1367 int
slap_ldap_response_code_register(struct berval * bv,int err)1368 slap_ldap_response_code_register( struct berval *bv, int err )
1369 {
1370           return slap_verbmask_register( slap_ldap_response_code_,
1371                     &slap_ldap_response_code, bv, err );
1372 }
1373 
1374 #ifdef HAVE_TLS
1375 static slap_verbmasks tlskey[] = {
1376           { BER_BVC("no"),    SB_TLS_OFF },
1377           { BER_BVC("yes"),   SB_TLS_ON },
1378           { BER_BVC("critical"),        SB_TLS_CRITICAL },
1379           { BER_BVNULL, 0 }
1380 };
1381 
1382 static slap_verbmasks crlkeys[] = {
1383                     { BER_BVC("none"),  LDAP_OPT_X_TLS_CRL_NONE },
1384                     { BER_BVC("peer"),  LDAP_OPT_X_TLS_CRL_PEER },
1385                     { BER_BVC("all"),   LDAP_OPT_X_TLS_CRL_ALL },
1386                     { BER_BVNULL, 0 }
1387           };
1388 
1389 static slap_verbmasks vfykeys[] = {
1390                     { BER_BVC("never"), LDAP_OPT_X_TLS_NEVER },
1391                     { BER_BVC("allow"), LDAP_OPT_X_TLS_ALLOW },
1392                     { BER_BVC("try"),   LDAP_OPT_X_TLS_TRY },
1393                     { BER_BVC("demand"),          LDAP_OPT_X_TLS_DEMAND },
1394                     { BER_BVC("hard"),  LDAP_OPT_X_TLS_HARD },
1395                     { BER_BVC("true"),  LDAP_OPT_X_TLS_HARD },
1396                     { BER_BVNULL, 0 }
1397           };
1398 #endif
1399 
1400 static slap_verbmasks methkey[] = {
1401           { BER_BVC("none"),  LDAP_AUTH_NONE },
1402           { BER_BVC("simple"),          LDAP_AUTH_SIMPLE },
1403 #ifdef HAVE_CYRUS_SASL
1404           { BER_BVC("sasl"),  LDAP_AUTH_SASL },
1405 #endif
1406           { BER_BVNULL, 0 }
1407 };
1408 
1409 static slap_verbmasks versionkey[] = {
1410           { BER_BVC("2"),               LDAP_VERSION2 },
1411           { BER_BVC("3"),               LDAP_VERSION3 },
1412           { BER_BVNULL, 0 }
1413 };
1414 
1415 int
slap_keepalive_parse(struct berval * val,void * bc,slap_cf_aux_table * tab0,const char * tabmsg,int unparse)1416 slap_keepalive_parse(
1417           struct berval *val,
1418           void *bc,
1419           slap_cf_aux_table *tab0,
1420           const char *tabmsg,
1421           int unparse )
1422 {
1423           if ( unparse ) {
1424                     slap_keepalive *sk = (slap_keepalive *)bc;
1425                     int rc = snprintf( val->bv_val, val->bv_len, "%d:%d:%d",
1426                               sk->sk_idle, sk->sk_probes, sk->sk_interval );
1427                     if ( rc < 0 ) {
1428                               return -1;
1429                     }
1430 
1431                     if ( (unsigned)rc >= val->bv_len ) {
1432                               return -1;
1433                     }
1434 
1435                     val->bv_len = rc;
1436 
1437           } else {
1438                     char *s = val->bv_val;
1439                     char *next;
1440                     slap_keepalive *sk = (slap_keepalive *)bc;
1441                     slap_keepalive sk2;
1442 
1443                     if ( s[0] == ':' ) {
1444                               sk2.sk_idle = 0;
1445                               s++;
1446 
1447                     } else {
1448                               sk2.sk_idle = strtol( s, &next, 10 );
1449                               if ( next == s || next[0] != ':' ) {
1450                                         return -1;
1451                               }
1452 
1453                               if ( sk2.sk_idle < 0 ) {
1454                                         return -1;
1455                               }
1456 
1457                               s = ++next;
1458                     }
1459 
1460                     if ( s[0] == ':' ) {
1461                               sk2.sk_probes = 0;
1462                               s++;
1463 
1464                     } else {
1465                               sk2.sk_probes = strtol( s, &next, 10 );
1466                               if ( next == s || next[0] != ':' ) {
1467                                         return -1;
1468                               }
1469 
1470                               if ( sk2.sk_probes < 0 ) {
1471                                         return -1;
1472                               }
1473 
1474                               s = ++next;
1475                     }
1476 
1477                     if ( *s == '\0' ) {
1478                               sk2.sk_interval = 0;
1479 
1480                     } else {
1481                               sk2.sk_interval = strtol( s, &next, 10 );
1482                               if ( next == s || next[0] != '\0' ) {
1483                                         return -1;
1484                               }
1485 
1486                               if ( sk2.sk_interval < 0 ) {
1487                                         return -1;
1488                               }
1489                     }
1490 
1491                     *sk = sk2;
1492 
1493                     ber_memfree( val->bv_val );
1494                     BER_BVZERO( val );
1495           }
1496 
1497           return 0;
1498 }
1499 
1500 static int
slap_sb_uri(struct berval * val,void * bcp,slap_cf_aux_table * tab0,const char * tabmsg,int unparse)1501 slap_sb_uri(
1502           struct berval *val,
1503           void *bcp,
1504           slap_cf_aux_table *tab0,
1505           const char *tabmsg,
1506           int unparse )
1507 {
1508           slap_bindconf *bc = bcp;
1509           if ( unparse ) {
1510                     if ( bc->sb_uri.bv_len >= val->bv_len )
1511                               return -1;
1512                     val->bv_len = bc->sb_uri.bv_len;
1513                     AC_MEMCPY( val->bv_val, bc->sb_uri.bv_val, val->bv_len );
1514           } else {
1515                     bc->sb_uri = *val;
1516 #ifdef HAVE_TLS
1517                     if ( ldap_is_ldaps_url( val->bv_val ))
1518                               bc->sb_tls_do_init = 1;
1519 #endif
1520           }
1521           return 0;
1522 }
1523 
1524 static slap_cf_aux_table bindkey[] = {
1525           { BER_BVC("uri="), 0, 'x', 1, slap_sb_uri },
1526           { BER_BVC("version="), offsetof(slap_bindconf, sb_version), 'i', 0, versionkey },
1527           { BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'i', 0, methkey },
1528           { BER_BVC("timeout="), offsetof(slap_bindconf, sb_timeout_api), 'i', 0, NULL },
1529           { BER_BVC("network-timeout="), offsetof(slap_bindconf, sb_timeout_net), 'i', 0, NULL },
1530           { BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, (slap_verbmasks *)dnNormalize },
1531           { BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
1532           { BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
1533           { BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
1534           { BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
1535           { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 1, NULL },
1536           { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, (slap_verbmasks *)authzNormalize },
1537           { BER_BVC("keepalive="), offsetof(slap_bindconf, sb_keepalive), 'x', 0, (slap_verbmasks *)slap_keepalive_parse },
1538           { BER_BVC("tcp-user-timeout="), offsetof(slap_bindconf, sb_tcp_user_timeout), 'u', 0, NULL },
1539 #ifdef HAVE_TLS
1540           /* NOTE: replace "14" with the actual index
1541            * of the first TLS-related line */
1542 #define aux_TLS (bindkey+14)  /* beginning of TLS keywords */
1543 
1544           { BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'i', 0, tlskey },
1545           { BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL },
1546           { BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL },
1547           { BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL },
1548           { BER_BVC("tls_cacertdir="), offsetof(slap_bindconf, sb_tls_cacertdir), 's', 1, NULL },
1549           { BER_BVC("tls_reqcert="), offsetof(slap_bindconf, sb_tls_reqcert), 's', 0, NULL },
1550           { BER_BVC("tls_reqsan="), offsetof(slap_bindconf, sb_tls_reqsan), 's', 0, NULL },
1551           { BER_BVC("tls_cipher_suite="), offsetof(slap_bindconf, sb_tls_cipher_suite), 's', 0, NULL },
1552           { BER_BVC("tls_protocol_min="), offsetof(slap_bindconf, sb_tls_protocol_min), 's', 0, NULL },
1553           { BER_BVC("tls_ecname="), offsetof(slap_bindconf, sb_tls_ecname), 's', 0, NULL },
1554 #ifdef HAVE_OPENSSL
1555           { BER_BVC("tls_crlcheck="), offsetof(slap_bindconf, sb_tls_crlcheck), 's', 0, NULL },
1556 #endif
1557 #endif
1558           { BER_BVNULL, 0, 0, 0, NULL }
1559 };
1560 
1561 /*
1562  * 's':   char *
1563  * 'b':   struct berval; if !NULL, normalize using ((slap_mr_normalize_func *)aux)
1564  * 'i':   int; if !NULL, compute using ((slap_verbmasks *)aux)
1565  * 'u':   unsigned
1566  * 'I':   long
1567  * 'U':   unsigned long
1568  */
1569 
1570 int
slap_cf_aux_table_parse(const char * word,void * dst,slap_cf_aux_table * tab0,LDAP_CONST char * tabmsg)1571 slap_cf_aux_table_parse( const char *word, void *dst, slap_cf_aux_table *tab0, LDAP_CONST char *tabmsg )
1572 {
1573           int rc = SLAP_CONF_UNKNOWN;
1574           slap_cf_aux_table *tab;
1575 
1576           for ( tab = tab0; !BER_BVISNULL( &tab->key ); tab++ ) {
1577                     if ( !strncasecmp( word, tab->key.bv_val, tab->key.bv_len ) ) {
1578                               char **cptr;
1579                               int *iptr, j;
1580                               unsigned *uptr;
1581                               long *lptr;
1582                               unsigned long *ulptr;
1583                               struct berval *bptr;
1584                               const char *val = word + tab->key.bv_len;
1585 
1586                               switch ( tab->type ) {
1587                               case 's':
1588                                         cptr = (char **)((char *)dst + tab->off);
1589                                         *cptr = ch_strdup( val );
1590                                         rc = 0;
1591                                         break;
1592 
1593                               case 'b':
1594                                         bptr = (struct berval *)((char *)dst + tab->off);
1595                                         if ( tab->aux != NULL ) {
1596                                                   struct berval       dn;
1597                                                   slap_mr_normalize_func *normalize = (slap_mr_normalize_func *)tab->aux;
1598 
1599                                                   ber_str2bv( val, 0, 0, &dn );
1600                                                   rc = normalize( 0, NULL, NULL, &dn, bptr, NULL );
1601 
1602                                         } else {
1603                                                   ber_str2bv( val, 0, 1, bptr );
1604                                                   rc = 0;
1605                                         }
1606                                         break;
1607 
1608                               case 'i':
1609                                         iptr = (int *)((char *)dst + tab->off);
1610 
1611                                         if ( tab->aux != NULL ) {
1612                                                   slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
1613 
1614                                                   assert( aux != NULL );
1615 
1616                                                   rc = 1;
1617                                                   for ( j = 0; !BER_BVISNULL( &aux[j].word ); j++ ) {
1618                                                             if ( !strcasecmp( val, aux[j].word.bv_val ) ) {
1619                                                                       *iptr = aux[j].mask;
1620                                                                       rc = 0;
1621                                                                       break;
1622                                                             }
1623                                                   }
1624 
1625                                         } else {
1626                                                   rc = lutil_atoix( iptr, val, 0 );
1627                                         }
1628                                         break;
1629 
1630                               case 'u':
1631                                         uptr = (unsigned *)((char *)dst + tab->off);
1632 
1633                                         rc = lutil_atoux( uptr, val, 0 );
1634                                         break;
1635 
1636                               case 'I':
1637                                         lptr = (long *)((char *)dst + tab->off);
1638 
1639                                         rc = lutil_atolx( lptr, val, 0 );
1640                                         break;
1641 
1642                               case 'U':
1643                                         ulptr = (unsigned long *)((char *)dst + tab->off);
1644 
1645                                         rc = lutil_atoulx( ulptr, val, 0 );
1646                                         break;
1647 
1648                               case 'x':
1649                                         if ( tab->aux != NULL ) {
1650                                                   struct berval value;
1651                                                   slap_cf_aux_table_parse_x *func = (slap_cf_aux_table_parse_x *)tab->aux;
1652 
1653                                                   ber_str2bv( val, 0, 1, &value );
1654 
1655                                                   rc = func( &value, (void *)((char *)dst + tab->off), tab, tabmsg, 0 );
1656 
1657                                         } else {
1658                                                   rc = 1;
1659                                         }
1660                                         break;
1661                               }
1662 
1663                               if ( rc ) {
1664                                         Debug( LDAP_DEBUG_ANY, "invalid %s value %s\n",
1665                                                   tabmsg, word );
1666                               }
1667 
1668                               return rc;
1669                     }
1670           }
1671 
1672           return rc;
1673 }
1674 
1675 int
slap_cf_aux_table_unparse(void * src,struct berval * bv,slap_cf_aux_table * tab0)1676 slap_cf_aux_table_unparse( void *src, struct berval *bv, slap_cf_aux_table *tab0 )
1677 {
1678           char buf[AC_LINE_MAX], *ptr;
1679           slap_cf_aux_table *tab;
1680           struct berval tmp;
1681 
1682           ptr = buf;
1683           for (tab = tab0; !BER_BVISNULL(&tab->key); tab++ ) {
1684                     char **cptr;
1685                     int *iptr, i;
1686                     unsigned *uptr;
1687                     long *lptr;
1688                     unsigned long *ulptr;
1689                     struct berval *bptr;
1690 
1691                     cptr = (char **)((char *)src + tab->off);
1692 
1693                     switch ( tab->type ) {
1694                     case 'b':
1695                               bptr = (struct berval *)((char *)src + tab->off);
1696                               cptr = &bptr->bv_val;
1697 
1698                     case 's':
1699                               if ( *cptr ) {
1700                                         *ptr++ = ' ';
1701                                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1702                                         if ( tab->quote ) *ptr++ = '"';
1703                                         ptr = lutil_strcopy( ptr, *cptr );
1704                                         if ( tab->quote ) *ptr++ = '"';
1705                               }
1706                               break;
1707 
1708                     case 'i':
1709                               iptr = (int *)((char *)src + tab->off);
1710 
1711                               if ( tab->aux != NULL ) {
1712                                         slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
1713 
1714                                         for ( i = 0; !BER_BVISNULL( &aux[i].word ); i++ ) {
1715                                                   if ( *iptr == aux[i].mask ) {
1716                                                             *ptr++ = ' ';
1717                                                             ptr = lutil_strcopy( ptr, tab->key.bv_val );
1718                                                             ptr = lutil_strcopy( ptr, aux[i].word.bv_val );
1719                                                             break;
1720                                                   }
1721                                         }
1722 
1723                               } else {
1724                                         *ptr++ = ' ';
1725                                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1726                                         ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%d", *iptr );
1727                               }
1728                               break;
1729 
1730                     case 'u':
1731                               uptr = (unsigned *)((char *)src + tab->off);
1732                               *ptr++ = ' ';
1733                               ptr = lutil_strcopy( ptr, tab->key.bv_val );
1734                               ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%u", *uptr );
1735                               break;
1736 
1737                     case 'I':
1738                               lptr = (long *)((char *)src + tab->off);
1739                               *ptr++ = ' ';
1740                               ptr = lutil_strcopy( ptr, tab->key.bv_val );
1741                               ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%ld", *lptr );
1742                               break;
1743 
1744                     case 'U':
1745                               ulptr = (unsigned long *)((char *)src + tab->off);
1746                               *ptr++ = ' ';
1747                               ptr = lutil_strcopy( ptr, tab->key.bv_val );
1748                               ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%lu", *ulptr );
1749                               break;
1750 
1751                     case 'x':
1752                               {
1753                                         char *saveptr=ptr;
1754                                         *ptr++ = ' ';
1755                                         ptr = lutil_strcopy( ptr, tab->key.bv_val );
1756                                         if ( tab->quote ) *ptr++ = '"';
1757                                         if ( tab->aux != NULL ) {
1758                                                   struct berval value;
1759                                                   slap_cf_aux_table_parse_x *func = (slap_cf_aux_table_parse_x *)tab->aux;
1760                                                   int rc;
1761 
1762                                                   value.bv_val = ptr;
1763                                                   value.bv_len = buf + sizeof( buf ) - ptr;
1764 
1765                                                   rc = func( &value, (void *)((char *)src + tab->off), tab, "(unparse)", 1 );
1766                                                   if ( rc == 0 ) {
1767                                                             if (value.bv_len) {
1768                                                                       ptr += value.bv_len;
1769                                                             } else {
1770                                                                       ptr = saveptr;
1771                                                                       break;
1772                                                             }
1773                                                   }
1774                                         }
1775                                         if ( tab->quote ) *ptr++ = '"';
1776                               }
1777                               break;
1778 
1779                     default:
1780                               assert( 0 );
1781                     }
1782           }
1783           tmp.bv_val = buf;
1784           tmp.bv_len = ptr - buf;
1785           ber_dupbv( bv, &tmp );
1786           return 0;
1787 }
1788 
1789 int
slap_tls_get_config(LDAP * ld,int opt,char ** val)1790 slap_tls_get_config( LDAP *ld, int opt, char **val )
1791 {
1792 #ifdef HAVE_TLS
1793           slap_verbmasks *keys;
1794           int i, ival;
1795 
1796           *val = NULL;
1797           switch( opt ) {
1798           case LDAP_OPT_X_TLS_CRLCHECK:
1799                     keys = crlkeys;
1800                     break;
1801           case LDAP_OPT_X_TLS_REQUIRE_CERT:
1802                     keys = vfykeys;
1803                     break;
1804           case LDAP_OPT_X_TLS_PROTOCOL_MIN: {
1805                     char buf[8];
1806                     ldap_pvt_tls_get_option( ld, opt, &ival );
1807                     snprintf( buf, sizeof( buf ), "%d.%d",
1808                               ( ival >> 8 ) & 0xff, ival & 0xff );
1809                     *val = ch_strdup( buf );
1810                     return 0;
1811                     }
1812           default:
1813                     return -1;
1814           }
1815           ldap_pvt_tls_get_option( ld, opt, &ival );
1816           for (i=0; !BER_BVISNULL(&keys[i].word); i++) {
1817                     if (keys[i].mask == ival) {
1818                               *val = ch_strdup( keys[i].word.bv_val );
1819                               return 0;
1820                     }
1821           }
1822 #endif
1823           return -1;
1824 }
1825 
1826 int
bindconf_tls_parse(const char * word,slap_bindconf * bc)1827 bindconf_tls_parse( const char *word, slap_bindconf *bc )
1828 {
1829 #ifdef HAVE_TLS
1830           if ( slap_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) {
1831                     bc->sb_tls_do_init = 1;
1832                     return 0;
1833           }
1834 #endif
1835           return -1;
1836 }
1837 
1838 int
bindconf_tls_unparse(slap_bindconf * bc,struct berval * bv)1839 bindconf_tls_unparse( slap_bindconf *bc, struct berval *bv )
1840 {
1841 #ifdef HAVE_TLS
1842           return slap_cf_aux_table_unparse( bc, bv, aux_TLS );
1843 #endif
1844           return -1;
1845 }
1846 
1847 int
bindconf_parse(const char * word,slap_bindconf * bc)1848 bindconf_parse( const char *word, slap_bindconf *bc )
1849 {
1850 #ifdef HAVE_TLS
1851           /* Detect TLS config changes explicitly */
1852           if ( bindconf_tls_parse( word, bc ) == 0 ) {
1853                     return 0;
1854           }
1855 #endif
1856           return slap_cf_aux_table_parse( word, bc, bindkey, "bind config" );
1857 }
1858 
1859 int
bindconf_unparse(slap_bindconf * bc,struct berval * bv)1860 bindconf_unparse( slap_bindconf *bc, struct berval *bv )
1861 {
1862           return slap_cf_aux_table_unparse( bc, bv, bindkey );
1863 }
1864 
bindconf_free(slap_bindconf * bc)1865 void bindconf_free( slap_bindconf *bc ) {
1866           if ( !BER_BVISNULL( &bc->sb_uri ) ) {
1867                     ch_free( bc->sb_uri.bv_val );
1868                     BER_BVZERO( &bc->sb_uri );
1869           }
1870           if ( !BER_BVISNULL( &bc->sb_binddn ) ) {
1871                     ch_free( bc->sb_binddn.bv_val );
1872                     BER_BVZERO( &bc->sb_binddn );
1873           }
1874           if ( !BER_BVISNULL( &bc->sb_cred ) ) {
1875                     ch_free( bc->sb_cred.bv_val );
1876                     BER_BVZERO( &bc->sb_cred );
1877           }
1878           if ( !BER_BVISNULL( &bc->sb_saslmech ) ) {
1879                     ch_free( bc->sb_saslmech.bv_val );
1880                     BER_BVZERO( &bc->sb_saslmech );
1881           }
1882           if ( bc->sb_secprops ) {
1883                     ch_free( bc->sb_secprops );
1884                     bc->sb_secprops = NULL;
1885           }
1886           if ( !BER_BVISNULL( &bc->sb_realm ) ) {
1887                     ch_free( bc->sb_realm.bv_val );
1888                     BER_BVZERO( &bc->sb_realm );
1889           }
1890           if ( !BER_BVISNULL( &bc->sb_authcId ) ) {
1891                     ch_free( bc->sb_authcId.bv_val );
1892                     BER_BVZERO( &bc->sb_authcId );
1893           }
1894           if ( !BER_BVISNULL( &bc->sb_authzId ) ) {
1895                     ch_free( bc->sb_authzId.bv_val );
1896                     BER_BVZERO( &bc->sb_authzId );
1897           }
1898 #ifdef HAVE_TLS
1899           if ( bc->sb_tls_cert ) {
1900                     ch_free( bc->sb_tls_cert );
1901                     bc->sb_tls_cert = NULL;
1902           }
1903           if ( bc->sb_tls_key ) {
1904                     ch_free( bc->sb_tls_key );
1905                     bc->sb_tls_key = NULL;
1906           }
1907           if ( bc->sb_tls_cacert ) {
1908                     ch_free( bc->sb_tls_cacert );
1909                     bc->sb_tls_cacert = NULL;
1910           }
1911           if ( bc->sb_tls_cacertdir ) {
1912                     ch_free( bc->sb_tls_cacertdir );
1913                     bc->sb_tls_cacertdir = NULL;
1914           }
1915           if ( bc->sb_tls_reqcert ) {
1916                     ch_free( bc->sb_tls_reqcert );
1917                     bc->sb_tls_reqcert = NULL;
1918           }
1919           if ( bc->sb_tls_reqsan ) {
1920                     ch_free( bc->sb_tls_reqsan );
1921                     bc->sb_tls_reqsan = NULL;
1922           }
1923           if ( bc->sb_tls_cipher_suite ) {
1924                     ch_free( bc->sb_tls_cipher_suite );
1925                     bc->sb_tls_cipher_suite = NULL;
1926           }
1927           if ( bc->sb_tls_protocol_min ) {
1928                     ch_free( bc->sb_tls_protocol_min );
1929                     bc->sb_tls_protocol_min = NULL;
1930           }
1931           if ( bc->sb_tls_ecname ) {
1932                     ch_free( bc->sb_tls_ecname );
1933                     bc->sb_tls_ecname = NULL;
1934           }
1935 #ifdef HAVE_OPENSSL
1936           if ( bc->sb_tls_crlcheck ) {
1937                     ch_free( bc->sb_tls_crlcheck );
1938                     bc->sb_tls_crlcheck = NULL;
1939           }
1940 #endif
1941           if ( bc->sb_tls_ctx ) {
1942                     ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
1943                     bc->sb_tls_ctx = NULL;
1944           }
1945 #endif
1946 }
1947 
1948 void
bindconf_tls_defaults(slap_bindconf * bc)1949 bindconf_tls_defaults( slap_bindconf *bc )
1950 {
1951 #ifdef HAVE_TLS
1952           if ( bc->sb_tls_do_init ) {
1953                     if ( !bc->sb_tls_cacert )
1954                               ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CACERTFILE,
1955                                         &bc->sb_tls_cacert );
1956                     if ( !bc->sb_tls_cacertdir )
1957                               ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CACERTDIR,
1958                                         &bc->sb_tls_cacertdir );
1959                     if ( !bc->sb_tls_cert )
1960                               ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CERTFILE,
1961                                         &bc->sb_tls_cert );
1962                     if ( !bc->sb_tls_key )
1963                               ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_KEYFILE,
1964                                         &bc->sb_tls_key );
1965                     if ( !bc->sb_tls_cipher_suite )
1966                               ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CIPHER_SUITE,
1967                                         &bc->sb_tls_cipher_suite );
1968                     if ( !bc->sb_tls_reqcert )
1969                               bc->sb_tls_reqcert = ch_strdup("demand");
1970                     if ( !bc->sb_tls_reqsan )
1971                               bc->sb_tls_reqsan = ch_strdup("allow");
1972                     if ( !bc->sb_tls_ecname )
1973                               slap_tls_get_config( slap_tls_ld, LDAP_OPT_X_TLS_ECNAME,
1974                                         &bc->sb_tls_ecname );
1975 #ifdef HAVE_OPENSSL
1976                     if ( !bc->sb_tls_crlcheck )
1977                               slap_tls_get_config( slap_tls_ld, LDAP_OPT_X_TLS_CRLCHECK,
1978                                         &bc->sb_tls_crlcheck );
1979 #endif
1980           }
1981 #endif
1982 }
1983 
1984 #ifdef HAVE_TLS
1985 static struct {
1986           const char *key;
1987           size_t offset;
1988           int opt;
1989 } bindtlsopts[] = {
1990           { "tls_cert", offsetof(slap_bindconf, sb_tls_cert), LDAP_OPT_X_TLS_CERTFILE },
1991           { "tls_key", offsetof(slap_bindconf, sb_tls_key), LDAP_OPT_X_TLS_KEYFILE },
1992           { "tls_cacert", offsetof(slap_bindconf, sb_tls_cacert), LDAP_OPT_X_TLS_CACERTFILE },
1993           { "tls_cacertdir", offsetof(slap_bindconf, sb_tls_cacertdir), LDAP_OPT_X_TLS_CACERTDIR },
1994           { "tls_cipher_suite", offsetof(slap_bindconf, sb_tls_cipher_suite), LDAP_OPT_X_TLS_CIPHER_SUITE },
1995           { "tls_ecname", offsetof(slap_bindconf, sb_tls_ecname), LDAP_OPT_X_TLS_ECNAME },
1996           {0, 0}
1997 };
1998 
bindconf_tls_set(slap_bindconf * bc,LDAP * ld)1999 int bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
2000 {
2001           int i, rc, newctx = 0, res = 0;
2002           char *ptr = (char *)bc, **word;
2003 
2004           if ( bc->sb_tls_do_init ) {
2005                     for (i=0; bindtlsopts[i].opt; i++) {
2006                               word = (char **)(ptr + bindtlsopts[i].offset);
2007                               if ( *word ) {
2008                                         rc = ldap_set_option( ld, bindtlsopts[i].opt, *word );
2009                                         if ( rc ) {
2010                                                   Debug( LDAP_DEBUG_ANY,
2011                                                             "bindconf_tls_set: failed to set %s to %s\n",
2012                                                                       bindtlsopts[i].key, *word );
2013                                                   res = -1;
2014                                         } else
2015                                                   newctx = 1;
2016                               }
2017                     }
2018                     if ( bc->sb_tls_reqcert ) {
2019                               rc = ldap_pvt_tls_config( ld, LDAP_OPT_X_TLS_REQUIRE_CERT,
2020                                         bc->sb_tls_reqcert );
2021                               if ( rc ) {
2022                                         Debug( LDAP_DEBUG_ANY,
2023                                                   "bindconf_tls_set: failed to set tls_reqcert to %s\n",
2024                                                             bc->sb_tls_reqcert );
2025                                         res = -1;
2026                               } else {
2027                                         newctx = 1;
2028                                         /* retrieve the parsed setting for later use */
2029                                         ldap_get_option( ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &bc->sb_tls_int_reqcert );
2030                               }
2031                     }
2032                     if ( bc->sb_tls_reqsan ) {
2033                               rc = ldap_pvt_tls_config( ld, LDAP_OPT_X_TLS_REQUIRE_SAN,
2034                                         bc->sb_tls_reqsan );
2035                               if ( rc ) {
2036                                         Debug( LDAP_DEBUG_ANY,
2037                                                   "bindconf_tls_set: failed to set tls_reqsan to %s\n",
2038                                                             bc->sb_tls_reqsan );
2039                                         res = -1;
2040                               } else {
2041                                         newctx = 1;
2042                                         /* retrieve the parsed setting for later use */
2043                                         ldap_get_option( ld, LDAP_OPT_X_TLS_REQUIRE_SAN, &bc->sb_tls_int_reqsan );
2044                               }
2045                     }
2046                     if ( bc->sb_tls_protocol_min ) {
2047                               rc = ldap_pvt_tls_config( ld, LDAP_OPT_X_TLS_PROTOCOL_MIN,
2048                                         bc->sb_tls_protocol_min );
2049                               if ( rc ) {
2050                                         Debug( LDAP_DEBUG_ANY,
2051                                                   "bindconf_tls_set: failed to set tls_protocol_min to %s\n",
2052                                                             bc->sb_tls_protocol_min );
2053                                         res = -1;
2054                               } else
2055                                         newctx = 1;
2056                     }
2057 #ifdef HAVE_OPENSSL
2058                     if ( bc->sb_tls_crlcheck ) {
2059                               rc = ldap_pvt_tls_config( ld, LDAP_OPT_X_TLS_CRLCHECK,
2060                                         bc->sb_tls_crlcheck );
2061                               if ( rc ) {
2062                                         Debug( LDAP_DEBUG_ANY,
2063                                                   "bindconf_tls_set: failed to set tls_crlcheck to %s\n",
2064                                                             bc->sb_tls_crlcheck );
2065                                         res = -1;
2066                               } else
2067                                         newctx = 1;
2068                     }
2069 #endif
2070                     if ( !res )
2071                               bc->sb_tls_do_init = 0;
2072           }
2073 
2074           if ( newctx ) {
2075                     int opt = 0;
2076 
2077                     if ( bc->sb_tls_ctx ) {
2078                               ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
2079                               bc->sb_tls_ctx = NULL;
2080                     }
2081                     rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
2082                     if ( rc )
2083                               res = rc;
2084                     else
2085                               ldap_get_option( ld, LDAP_OPT_X_TLS_CTX, &bc->sb_tls_ctx );
2086           } else if ( bc->sb_tls_ctx ) {
2087                     rc = ldap_set_option( ld, LDAP_OPT_X_TLS_CTX, bc->sb_tls_ctx );
2088                     if ( rc == LDAP_SUCCESS ) {
2089                               /* these options aren't actually inside the ctx, so have to be set again */
2090                               ldap_set_option( ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &bc->sb_tls_int_reqcert );
2091                               ldap_set_option( ld, LDAP_OPT_X_TLS_REQUIRE_SAN, &bc->sb_tls_int_reqsan );
2092                     } else
2093                               res = rc;
2094           }
2095 
2096           return res;
2097 }
2098 #endif
2099 
2100 /*
2101  * set connection keepalive options
2102  */
2103 void
slap_client_keepalive(LDAP * ld,slap_keepalive * sk)2104 slap_client_keepalive(LDAP *ld, slap_keepalive *sk)
2105 {
2106           if (!sk) return;
2107 
2108           if ( sk->sk_idle ) {
2109                     ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_IDLE, &sk->sk_idle );
2110           }
2111 
2112           if ( sk->sk_probes ) {
2113                     ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_PROBES, &sk->sk_probes );
2114           }
2115 
2116           if ( sk->sk_interval ) {
2117                     ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_INTERVAL, &sk->sk_interval );
2118           }
2119 
2120           return;
2121 }
2122 
2123 /*
2124  * connect to a client using the bindconf data
2125  * note: should move "version" into bindconf...
2126  */
2127 int
slap_client_connect(LDAP ** ldp,slap_bindconf * sb)2128 slap_client_connect( LDAP **ldp, slap_bindconf *sb )
2129 {
2130           LDAP                *ld = NULL;
2131           int                 rc;
2132           struct timeval tv;
2133 
2134           /* Init connection to provider */
2135           rc = ldap_initialize( &ld, sb->sb_uri.bv_val );
2136           if ( rc != LDAP_SUCCESS ) {
2137                     Debug( LDAP_DEBUG_ANY,
2138                               "slap_client_connect: "
2139                               "ldap_initialize(%s) failed (%d)\n",
2140                               sb->sb_uri.bv_val, rc );
2141                     return rc;
2142           }
2143 
2144           if ( sb->sb_version != 0 ) {
2145                     ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
2146                               (const void *)&sb->sb_version );
2147           }
2148 
2149           if ( sb->sb_timeout_api ) {
2150                     tv.tv_sec = sb->sb_timeout_api;
2151                     tv.tv_usec = 0;
2152                     ldap_set_option( ld, LDAP_OPT_TIMEOUT, &tv );
2153           }
2154 
2155           if ( sb->sb_timeout_net ) {
2156                     tv.tv_sec = sb->sb_timeout_net;
2157                     tv.tv_usec = 0;
2158                     ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, &tv );
2159           }
2160 
2161           /* setting network keepalive options */
2162           slap_client_keepalive(ld, &sb->sb_keepalive);
2163 
2164 #ifdef HAVE_TLS
2165           rc = bindconf_tls_set( sb, ld );
2166           if ( rc ) {
2167                     Debug( LDAP_DEBUG_ANY,
2168                               "slap_client_connect: "
2169                               "URI=%s TLS context initialization failed (%d)\n",
2170                               sb->sb_uri.bv_val, rc );
2171                     goto done;
2172           }
2173 #endif
2174 
2175           /* Bind */
2176           if ( sb->sb_tls ) {
2177                     rc = ldap_start_tls_s( ld, NULL, NULL );
2178                     if ( rc != LDAP_SUCCESS ) {
2179                               Debug( LDAP_DEBUG_ANY,
2180                                         "slap_client_connect: URI=%s "
2181                                         "%s, ldap_start_tls failed (%d)\n",
2182                                         sb->sb_uri.bv_val,
2183                                         sb->sb_tls == SB_TLS_CRITICAL ?
2184                                                   "Error" : "Warning",
2185                                         rc );
2186                               if ( sb->sb_tls == SB_TLS_CRITICAL ) {
2187                                         goto done;
2188                               }
2189                     }
2190           }
2191 
2192           if ( sb->sb_method == LDAP_AUTH_SASL ) {
2193 #ifdef HAVE_CYRUS_SASL
2194                     void *defaults;
2195 
2196                     if ( sb->sb_secprops != NULL ) {
2197                               rc = ldap_set_option( ld,
2198                                         LDAP_OPT_X_SASL_SECPROPS, sb->sb_secprops);
2199 
2200                               if( rc != LDAP_OPT_SUCCESS ) {
2201                                         Debug( LDAP_DEBUG_ANY,
2202                                                   "slap_client_connect: "
2203                                                   "error, ldap_set_option "
2204                                                   "(%s,SECPROPS,\"%s\") failed!\n",
2205                                                   sb->sb_uri.bv_val, sb->sb_secprops );
2206                                         goto done;
2207                               }
2208                     }
2209 
2210                     defaults = lutil_sasl_defaults( ld,
2211                               sb->sb_saslmech.bv_val,
2212                               sb->sb_realm.bv_val,
2213                               sb->sb_authcId.bv_val,
2214                               sb->sb_cred.bv_val,
2215                               sb->sb_authzId.bv_val );
2216                     if ( defaults == NULL ) {
2217                               rc = LDAP_OTHER;
2218                               goto done;
2219                     }
2220 
2221                     rc = ldap_sasl_interactive_bind_s( ld,
2222                                         sb->sb_binddn.bv_val,
2223                                         sb->sb_saslmech.bv_val,
2224                                         NULL, NULL,
2225                                         LDAP_SASL_QUIET,
2226                                         lutil_sasl_interact,
2227                                         defaults );
2228 
2229                     lutil_sasl_freedefs( defaults );
2230 
2231                     /* FIXME: different error behaviors according to
2232                      *        1) return code
2233                      *        2) on err policy : exit, retry, backoff ...
2234                      */
2235                     if ( rc != LDAP_SUCCESS ) {
2236                               static struct berval bv_GSSAPI = BER_BVC( "GSSAPI" );
2237 
2238                               Debug( LDAP_DEBUG_ANY, "slap_client_connect: URI=%s "
2239                                         "ldap_sasl_interactive_bind_s failed (%d)\n",
2240                                         sb->sb_uri.bv_val, rc );
2241 
2242                               /* FIXME (see above comment) */
2243                               /* if Kerberos credentials cache is not active, retry */
2244                               if ( ber_bvcmp( &sb->sb_saslmech, &bv_GSSAPI ) == 0 &&
2245                                         rc == LDAP_LOCAL_ERROR )
2246                               {
2247                                         rc = LDAP_SERVER_DOWN;
2248                               }
2249 
2250                               goto done;
2251                     }
2252 #else /* HAVE_CYRUS_SASL */
2253                     /* Should never get here, we trapped this at config time */
2254                     assert(0);
2255                     Debug( LDAP_DEBUG_SYNC, "not compiled with SASL support\n" );
2256                     rc = LDAP_OTHER;
2257                     goto done;
2258 #endif
2259 
2260           } else if ( sb->sb_method == LDAP_AUTH_SIMPLE ) {
2261                     rc = ldap_sasl_bind_s( ld,
2262                               sb->sb_binddn.bv_val, LDAP_SASL_SIMPLE,
2263                               &sb->sb_cred, NULL, NULL, NULL );
2264                     if ( rc != LDAP_SUCCESS ) {
2265                               Debug( LDAP_DEBUG_ANY, "slap_client_connect: "
2266                                         "URI=%s DN=\"%s\" "
2267                                         "ldap_sasl_bind_s failed (%d)\n",
2268                                         sb->sb_uri.bv_val, sb->sb_binddn.bv_val, rc );
2269                               goto done;
2270                     }
2271           }
2272 
2273 done:;
2274           if ( rc ) {
2275                     if ( ld ) {
2276                               ldap_unbind_ext( ld, NULL, NULL );
2277                               *ldp = NULL;
2278                     }
2279 
2280           } else {
2281                     *ldp = ld;
2282           }
2283 
2284           return rc;
2285 }
2286 
2287 /* -------------------------------------- */
2288 
2289 
2290 static char *
strtok_quote(char * line,char * sep,char ** quote_ptr,int * iqp)2291 strtok_quote( char *line, char *sep, char **quote_ptr, int *iqp )
2292 {
2293           int                 inquote;
2294           char                *tmp;
2295           static char         *next;
2296 
2297           *quote_ptr = NULL;
2298           if ( line != NULL ) {
2299                     next = line;
2300           }
2301           while ( *next && strchr( sep, *next ) ) {
2302                     next++;
2303           }
2304 
2305           if ( *next == '\0' ) {
2306                     next = NULL;
2307                     return( NULL );
2308           }
2309           tmp = next;
2310 
2311           for ( inquote = 0; *next; ) {
2312                     switch ( *next ) {
2313                     case '"':
2314                               if ( inquote ) {
2315                                         inquote = 0;
2316                               } else {
2317                                         inquote = 1;
2318                               }
2319                               AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
2320                               break;
2321 
2322                     case '\\':
2323                               if ( next[1] )
2324                                         AC_MEMCPY( next,
2325                                                       next + 1, strlen( next + 1 ) + 1 );
2326                               next++;             /* dont parse the escaped character */
2327                               break;
2328 
2329                     default:
2330                               if ( ! inquote ) {
2331                                         if ( strchr( sep, *next ) != NULL ) {
2332                                                   *quote_ptr = next;
2333                                                   *next++ = '\0';
2334                                                   return( tmp );
2335                                         }
2336                               }
2337                               next++;
2338                               break;
2339                     }
2340           }
2341           *iqp = inquote;
2342 
2343           return( tmp );
2344 }
2345 
2346 static char         buf[AC_LINE_MAX];
2347 static char         *line;
2348 static size_t lmax, lcur;
2349 
2350 #define CATLINE( buf ) \
2351           do { \
2352                     size_t len = strlen( buf ); \
2353                     while ( lcur + len + 1 > lmax ) { \
2354                               lmax += AC_LINE_MAX; \
2355                               line = (char *) ch_realloc( line, lmax ); \
2356                     } \
2357                     strcpy( line + lcur, buf ); \
2358                     lcur += len; \
2359           } while( 0 )
2360 
2361 static void
fp_getline_init(ConfigArgs * c)2362 fp_getline_init(ConfigArgs *c) {
2363           c->lineno = -1;
2364           buf[0] = '\0';
2365 }
2366 
2367 static int
fp_getline(FILE * fp,ConfigArgs * c)2368 fp_getline( FILE *fp, ConfigArgs *c )
2369 {
2370           char      *p;
2371 
2372           lcur = 0;
2373           CATLINE(buf);
2374           c->lineno++;
2375 
2376           /* avoid stack of bufs */
2377           if ( strncasecmp( line, "include", STRLENOF( "include" ) ) == 0 ) {
2378                     buf[0] = '\0';
2379                     c->line = line;
2380                     return(1);
2381           }
2382 
2383           while ( fgets( buf, sizeof( buf ), fp ) ) {
2384                     p = strchr( buf, '\n' );
2385                     if ( p ) {
2386                               if ( p > buf && p[-1] == '\r' ) {
2387                                         --p;
2388                               }
2389                               *p = '\0';
2390                     }
2391                     /* XXX ugly */
2392                     c->line = line;
2393                     if ( line[0]
2394                                         && ( p = line + strlen( line ) - 1 )[0] == '\\'
2395                                         && p[-1] != '\\' )
2396                     {
2397                               p[0] = '\0';
2398                               lcur--;
2399 
2400                     } else {
2401                               if ( !isspace( (unsigned char)buf[0] ) ) {
2402                                         return(1);
2403                               }
2404                               buf[0] = ' ';
2405                     }
2406                     CATLINE(buf);
2407                     c->lineno++;
2408           }
2409 
2410           buf[0] = '\0';
2411           c->line = line;
2412           return(line[0] ? 1 : 0);
2413 }
2414 
2415 int
config_fp_parse_line(ConfigArgs * c)2416 config_fp_parse_line(ConfigArgs *c)
2417 {
2418           char *token;
2419           static char *const hide[] = {
2420                     "rootpw", "replica", "syncrepl",  /* in slapd */
2421                     "acl-bind", "acl-method", "idassert-bind",  /* in back-ldap */
2422                     "acl-passwd", "bindpw",  /* in back-<ldap/meta> */
2423                     "pseudorootpw",  /* in back-meta */
2424                     "dbpasswd",  /* in back-sql */
2425                     NULL
2426           };
2427           static char *const raw[] = {
2428                     "attributetype", "objectclass", "ditcontentrule", "ldapsyntax", NULL };
2429           char *quote_ptr;
2430           int i = (int)(sizeof(hide)/sizeof(hide[0])) - 1;
2431           int inquote = 0;
2432 
2433           c->tline = ch_strdup(c->line);
2434           c->linelen = strlen(c->line);
2435           token = strtok_quote(c->tline, " \t", &quote_ptr, &inquote);
2436 
2437           if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
2438           if(quote_ptr) *quote_ptr = ' ';
2439           Debug(LDAP_DEBUG_CONFIG, "%s (%s%s)\n", c->log,
2440                     hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "");
2441           if(quote_ptr) *quote_ptr = '\0';
2442 
2443           for(;; token = strtok_quote(NULL, " \t", &quote_ptr, &inquote)) {
2444                     if(c->argc >= c->argv_size) {
2445                               char **tmp;
2446                               tmp = ch_realloc(c->argv, (c->argv_size + ARGS_STEP) * sizeof(*c->argv));
2447                               if(!tmp) {
2448                                         Debug(LDAP_DEBUG_ANY, "%s: out of memory\n", c->log );
2449                                         return -1;
2450                               }
2451                               c->argv = tmp;
2452                               c->argv_size += ARGS_STEP;
2453                     }
2454                     if(token == NULL)
2455                               break;
2456                     c->argv[c->argc++] = token;
2457           }
2458           c->argv[c->argc] = NULL;
2459           if (inquote) {
2460                     /* these directives parse c->line independently of argv tokenizing */
2461                     for(i = 0; raw[i]; i++) if (!strcasecmp(c->argv[0], raw[i])) return 0;
2462 
2463                     Debug(LDAP_DEBUG_ANY, "%s: unterminated quoted string \"%s\"\n", c->log, c->argv[c->argc-1] );
2464                     return -1;
2465           }
2466           return(0);
2467 }
2468 
2469 void
config_destroy()2470 config_destroy( )
2471 {
2472           ucdata_unload( UCDATA_ALL );
2473           if ( frontendDB ) {
2474                     /* NOTE: in case of early exit, frontendDB can be NULL */
2475                     if ( frontendDB->be_schemandn.bv_val )
2476                               free( frontendDB->be_schemandn.bv_val );
2477                     if ( frontendDB->be_schemadn.bv_val )
2478                               free( frontendDB->be_schemadn.bv_val );
2479                     if ( frontendDB->be_acl )
2480                               acl_destroy( frontendDB->be_acl );
2481           }
2482           free( line );
2483           if ( slapd_args_file )
2484                     free ( slapd_args_file );
2485           if ( slapd_pid_file )
2486                     free ( slapd_pid_file );
2487           if ( default_passwd_hash )
2488                     ldap_charray_free( default_passwd_hash );
2489 }
2490 
2491 char **
slap_str2clist(char *** out,char * in,const char * brkstr)2492 slap_str2clist( char ***out, char *in, const char *brkstr )
2493 {
2494           char      *str;
2495           char      *s;
2496           char      *lasts;
2497           int       i, j;
2498           char      **new;
2499 
2500           /* find last element in list */
2501           for (i = 0; *out && (*out)[i]; i++);
2502 
2503           /* protect the input string from strtok */
2504           str = ch_strdup( in );
2505 
2506           if ( *str == '\0' ) {
2507                     free( str );
2508                     return( *out );
2509           }
2510 
2511           /* Count words in string */
2512           j=1;
2513           for ( s = str; *s; s++ ) {
2514                     if ( strchr( brkstr, *s ) != NULL ) {
2515                               j++;
2516                     }
2517           }
2518 
2519           *out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
2520           new = *out + i;
2521           for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
2522                     s != NULL;
2523                     s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
2524           {
2525                     *new = ch_strdup( s );
2526                     new++;
2527           }
2528 
2529           *new = NULL;
2530           free( str );
2531           return( *out );
2532 }
2533 
config_generic_wrapper(Backend * be,const char * fname,int lineno,int argc,char ** argv)2534 int config_generic_wrapper( Backend *be, const char *fname, int lineno,
2535           int argc, char **argv )
2536 {
2537           ConfigArgs c = { 0 };
2538           ConfigTable *ct;
2539           int rc;
2540 
2541           c.be = be;
2542           c.fname = fname;
2543           c.lineno = lineno;
2544           c.argc = argc;
2545           c.argv = argv;
2546           c.valx = -1;
2547           c.line = line;
2548           c.op = SLAP_CONFIG_ADD;
2549           snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
2550 
2551           rc = SLAP_CONF_UNKNOWN;
2552           ct = config_find_keyword( be->be_cf_ocs->co_table, &c );
2553           if ( ct ) {
2554                     c.table = be->be_cf_ocs->co_type;
2555                     rc = config_add_vals( ct, &c );
2556           }
2557           return rc;
2558 }
2559 
2560 /* See if the given URL (in plain and parsed form) matches
2561  * any of the server's listener addresses. Return matching
2562  * Listener or NULL for no match.
2563  */
config_check_my_url(const char * url,LDAPURLDesc * lud)2564 Listener *config_check_my_url( const char *url, LDAPURLDesc *lud )
2565 {
2566           Listener **l = slapd_get_listeners();
2567           int i, isMe;
2568 
2569           /* Try a straight compare with Listener strings */
2570           for ( i=0; l && l[i]; i++ ) {
2571                     if ( !strcasecmp( url, l[i]->sl_url.bv_val )) {
2572                               return l[i];
2573                     }
2574           }
2575 
2576           isMe = 0;
2577           /* If hostname is empty, or is localhost, or matches
2578            * our hostname, this url refers to this host.
2579            * Compare it against listeners and ports.
2580            */
2581           if ( !lud->lud_host || !lud->lud_host[0] ||
2582                     !strncasecmp("localhost", lud->lud_host,
2583                               STRLENOF("localhost")) ||
2584                     !strcasecmp( global_host, lud->lud_host )) {
2585 
2586                     for ( i=0; l && l[i]; i++ ) {
2587                               LDAPURLDesc *lu2;
2588                               ldap_url_parse( l[i]->sl_url.bv_val, &lu2 );
2589                               do {
2590                                         if ( strcasecmp( lud->lud_scheme,
2591                                                   lu2->lud_scheme ))
2592                                                   break;
2593                                         if ( lud->lud_port != lu2->lud_port )
2594                                                   break;
2595                                         /* Listener on ANY address */
2596                                         if ( !lu2->lud_host || !lu2->lud_host[0] ) {
2597                                                   isMe = 1;
2598                                                   break;
2599                                         }
2600                                         /* URL on ANY address */
2601                                         if ( !lud->lud_host || !lud->lud_host[0] ) {
2602                                                   isMe = 1;
2603                                                   break;
2604                                         }
2605                                         /* Listener has specific host, must
2606                                          * match it
2607                                          */
2608                                         if ( !strcasecmp( lud->lud_host,
2609                                                   lu2->lud_host )) {
2610                                                   isMe = 1;
2611                                                   break;
2612                                         }
2613                               } while(0);
2614                               ldap_free_urldesc( lu2 );
2615                               if ( isMe ) {
2616                                         return l[i];
2617                               }
2618                     }
2619           }
2620           return NULL;
2621 }
2622